Beispiel #1
0
    async def readdir(self, inode, off, token):
        assert inode == pyfuse3.ROOT_INODE

        if off < len(self.info_files):
            info_file = self.info_files[off]
            pyfuse3.readdir_reply(token, info_file.name, await
                                  self.getattr(info_file.inode), off + 1)
Beispiel #2
0
    async def readdir(self, dir_inode, offset, token):
        folder = self._inode_to_folder[dir_inode]

        logger.debug(
            f'readdir() called for inode {dir_inode} (folder {folder.name}), offset {offset}, token {token}'
        )

        if folder:
            for i, subfolder in enumerate(folder.children[offset:],
                                          offset + 1):
                inode = self._folder_to_inode[subfolder]
                attr = await self.getattr(inode)

                logger.debug(
                    f'Contents: {dir_inode}[{i}] = {inode} (folder {subfolder.name})'
                )
                if not pyfuse3.readdir_reply(token, os.fsencode(
                        subfolder.name), attr, i):
                    return

            offset = max(0, offset - len(folder.children))
            assets = folder.sorted_named_assets[offset:]
            for i, (name,
                    asset) in enumerate(assets,
                                        len(folder.children) + offset + 1):
                inode = self._folder_asset_to_inode[(folder, asset)]
                attr = await self.getattr(inode)

                logger.debug(
                    f'Contents: {dir_inode}[{i}] = {inode} (asset {asset.id})')
                if not pyfuse3.readdir_reply(token, os.fsencode(name), attr,
                                             i):
                    return
        else:
            raise FUSEError(errno.ENOENT)
Beispiel #3
0
    async def readdir(self, fh, start_id, token):
        assert fh == pyfuse3.ROOT_INODE

        # only one entry
        if start_id == 0:
            pyfuse3.readdir_reply(
                token, self.hello_name, await self.getattr(self.hello_inode), 1)
        return
Beispiel #4
0
    async def readdir(self, inode, off, token):
        if off == 0:
            off = -1

        cursor2 = self.db.cursor()
        cursor2.execute(
            "SELECT * FROM contents WHERE parent_inode=? AND rowid > ? ORDER BY rowid",
            (inode, off))
        for row in cursor2:
            pyfuse3.readdir_reply(token, row['name'], await
                                  self.getattr(row['inode']), row['rowid'])
Beispiel #5
0
    async def readdir(self, fh, start_id, token):
        #node = self.packages.get_inode(start_id)
        #print('readdir',fh, 'off', start_id)
        '''print(token.size)'''
        if fh == pyfuse3.ROOT_INODE:
            for node in self.dirs:
                if node['inode'] <= start_id:
                    continue
                name = f"{node['name']}"
                if not pyfuse3.readdir_reply(token, f"{name}".encode(), await
                                             self.getattr(node['inode']
                                                          ), node['inode']):
                    break
        else:
            node = self.get_node(fh)
            if not node:
                return

            DEBUGPKGNAME = "vlc"
            if node['name'] == DEBUGPKGNAME:
                print('  node name', fh, node['name'], 'offset:', start_id)
            offset = fh * 100000
            if start_id >= offset:
                return

            # generate symlinks : Dependencies (and optionals ?)
            # BUG TODO readdir_reply return false after 16 links !!!
            if fh > 600:  # only one level
                return
            offset += 10
            i = 0  # count bug -> stop always at 17 !!! (vlc, gimp ...)
            for link in range(5, 48):
                if fh == link:
                    continue
                linknode = self.get_file(str(link))
                if not linknode:
                    return
                offset += 1
                mode = await self.getattr(linknode['inode'])
                mode.st_mode = (stat.S_IFLNK | 0o555)
                mode.st_nlink = linknode['inode']
                #print('  link create for:', node['name'], offset, 'target:', linknode['name'], linknode['inode'])
                if not pyfuse3.readdir_reply(
                        token, f"{linknode['name']}.link".encode(), mode,
                        offset):
                    '''
                    print(dir(token))

                    print(f"ERROR readdir_reply (no:{i} , {token['size']}) link: {linknode['name']} inode: {offset} mode_ino: {mode.st_ino} {mode}")
                    '''
                    return
                i += 1
        return
Beispiel #6
0
    async def readdir(self, inode, off, token):
        path = self._inode_to_path(inode)
        log.debug('reading %s', path)
        entries = []
        for name in os.listdir(path):
            if name == '.' or name == '..':
                continue
            attr = self._getattr(path=os.path.join(path, name))
            entries.append((attr.st_ino, name, attr))

        log.debug('read %d entries, starting at %d', len(entries), off)

        # This is not fully posix compatible. If there are hardlinks
        # (two names with the same inode), we don't have a unique
        # offset to start in between them. Note that we cannot simply
        # count entries, because then we would skip over entries
        # (or return them more than once) if the number of directory
        # entries changes between two calls to readdir().
        for (ino, name, attr) in sorted(entries):
            if ino <= off:
                continue
            if not pyfuse3.readdir_reply(
                    token, fsencode(name), attr, ino):
                break
            self._add_path(attr.st_ino, os.path.join(path, name))
Beispiel #7
0
    async def readdir(self, inode, off, token):
        path = self._inode_to_path(inode, fullpath=True)
        log.debug('reading %s', path)

        parent_id = self._get_degoo_id(path)
        children = self._get_degoo_childs(parent_id)

        # If dir has not children and it is lazy mode, degoo it is called to get the content
        if self._mode == 'lazy' and len(children) == 0:
            degoo.tree(dir_id=inode, mode=self._mode)
            self._refresh_path()
            children = self._get_degoo_childs(parent_id)

        entries = []
        for element in children:
            attr = self._get_degoo_attrs(element['FilePath'])
            entries.append((attr.st_ino, element['Name'], attr))

        for (ino, name, attr) in sorted(entries):
            if ino <= off:
                continue
            if not pyfuse3.readdir_reply(token, fsencode(name), attr, ino):
                break
            self._add_path(attr.st_ino,
                           self._get_degoo_element_path_by_id(attr.st_ino))
Beispiel #8
0
    async def readdir(self, fh: int, start_index: int,
                      token: pyfuse3.ReaddirToken):
        """
        Read entries in open directory fh.

        This method should list the contents of directory fh (as returned by a prior opendir call),
        starting at the entry identified by start_id.

        Instead of returning the directory entries directly, the method must call readdir_reply for
        each directory entry. If readdir_reply returns True, the file system must increase the lookup
        count for the provided directory entry by one and call readdir_reply again for the next entry
        (if any). If readdir_reply returns False, the lookup count must not be increased and the method
        should return without further calls to readdir_reply.

        The start_id parameter will be either zero (in which case listing should begin with the first
        entry) or it will correspond to a value that was previously passed by the file system to the
        readdir_reply function in the next_id parameter.

        If entries are added or removed during a readdir cycle, they may or may not be returned.
        However, they must not cause other entries to be skipped or returned more than once.

        . and .. entries may be included but are not required. However, if they are reported the
        filesystem must not increase the lookup count for the corresponding inodes (even if
        readdir_reply returns True).
        """
        info = self._get_fh_info(fh)

        for i, (name, inode) in enumerate(info.children()):
            if i < start_index:
                continue
            if not pyfuse3.readdir_reply(token, name.encode(), await
                                         self.getattr(inode), i + 1):
                break
Beispiel #9
0
    async def readdir(self, fh, start_id, token):
        obj = self.fh[fh]

        async for (name, inode_obj, next_id) in obj.read(start_id):
            inode = self.inode.allocate(inode_obj)
            attr = self.__makeattr(inode, inode_obj)
            if not pyfuse3.readdir_reply(token, name, attr, next_id):
                self.inode.deallocate(inode)
                break
Beispiel #10
0
    async def readdir(self, inode, off, token):
        if not off:
            off = -1

        path = self._inode_to_path(inode)
        LOG.info('readdir %s [inode %s]', path, inode)
        LOG.debug('\toffset %s', off)
        entries = self._inode2entries[inode]
        LOG.info('read %d entries, starting at %d', len(entries), off)

        # Sort them for the offset
        for (ino, name, entry) in entries:
            if ino <= off:
                continue
            attrs = self._stats2entry(entry)
            pyfuse3.readdir_reply(token, fsencode(name), attrs, ino)
            # ignore result?.... or if not: break?

        return False  # over
Beispiel #11
0
    async def readdir(self, inode, off, token):
        childs = list(self.files.get_file(inode).content.values())

        for i in filter(lambda i: i > off, childs):
            child = self.files.get_file(i)
            r = pyfuse3.readdir_reply(
                token, child.name,
                self.files.getattr_from_file(child), i
            )
            if not r:
                return
Beispiel #12
0
    async def readdir(self, fh, off, token):
        logvfs.debug("readdir(%s,%s)" % (fh, off))

        assert fh == pyfuse3.ROOT_INODE

        inodes = self.inodes[off:]

        for idx, inode in enumerate(inodes, off):
            file = self.files[inode]
            if not pyfuse3.readdir_reply(token, file.fname, file.attr,
                                         idx + 1):
                break
    async def readdir(self, inode, off, token):
        self.logger.debug("readdir: %s %s", inode, off)

        entry = self._entry_by_inode(inode)
        for index, child_inode in enumerate(
                itertools.islice(entry.childs.values(), off, None), off + 1):
            child = self._entry_by_inode(child_inode)

            if not pyfuse3.readdir_reply(
                    token, child.filename.encode(self._filename_encoding),
                    await self._gen_attr(child), index):
                break
        return
Beispiel #14
0
 async def readdir(self, fh, start_id, token):
     """
     读取目录信息,这个方法会被频繁调用
     所以为了防止百度因为频繁请求封了账号这里加缓存默认1个小时更新保险一点,默认值在entity.Env里可以调整
     缺点就是网页版或者客户端中的更新就不会那么实时了
     因为这个方法会不断的被执行, 所以这里需要加文件列表数量校验
     调试中看来start_id会一直更新,除非切换了inode也就是参数上的fh,(fh逻辑上算是唯一标识,相当于切换了目录的话,start_id就会从0开始)
     需要注意的是这里的inode实际上并不一定是文件系统理解中的inode,但逻辑上是一样的,每个目录和文件都需要有inode。
     此处根目录没有,所以做判断 如果fh(inode) = 根inode 则默认获取根目录列表
     :param fh: fh(inode) 逻辑上的inode,用作文件或文件夹的唯一标识
     :param start_id: start_id 是 pyfuse3.readdir_reply 的最后一个参数,会作为未来的readdir调用参数传入, 应当用作读取区间的标识,
     上层不会一次性读取所有的值, 而是会分多次调用readdir,传入start_id 取不同的区间,实现上需要从start_id开始读取到目录最大下标, 需要注意这点
     :param token:
     :return:
     """
     f = BDFile.get_from_fs_id(fh)
     files = self.fs.dir_cache('/' if not f else f.path,
                               pyfuse3.ROOT_INODE if not f else f.fs_id)
     max_len = len(files)
     for i in range(start_id, max_len):
         pyfuse3.readdir_reply(token, files[i].filename_bytes, await
                               self.getattr(files[i].fs_id, None), i + 1)
Beispiel #15
0
 async def readdir(self, inode: INode, start_id: int,
                   token: ReaddirToken) -> None:
     dir_path = self.paths[inode]
     files = []
     for fname in pyfuse3.listdir(dir_path):
         entry_attrs = self._get_entry_attrs(self.paths.join(inode, fname))
         if entry_attrs.st_ino > start_id:
             files.append((entry_attrs.st_ino, fname, entry_attrs))
     for ino, fname, entry_attrs in sorted(files):
         if not pyfuse3.readdir_reply(token, os.fsencode(fname),
                                      entry_attrs, ino):
             break
         self.paths[ino] = os.path.join(dir_path, fname)
Beispiel #16
0
    async def readdir(self, inode, start_id, token):
        """Read entries in open directory *inode*.
        This method should list the contents of directory *inode* (as returned by a
        prior `opendir` call), starting at the entry identified by *start_id*.
        Instead of returning the directory entries directly, the method must
        call `readdir_reply` for each directory entry. If `readdir_reply`
        returns True, the file system must increase the lookup count for the
        provided directory entry by one and call `readdir_reply` again for the
        next entry (if any). If `readdir_reply` returns False, the lookup count
        must *not* be increased and the method should return without further
        calls to `readdir_reply`.
        The *start_id* parameter will be either zero (in which case listing
        should begin with the first entry) or it will correspond to a value that
        was previously passed by the file system to the `readdir_reply`
        function in the *next_id* parameter.
        If entries are added or removed during a `readdir` cycle, they may or
        may not be returned. However, they must not cause other entries to be
        skipped or returned more than once.
        :file:`.` and :file:`..` entries may be included but are not
        required. However, if they are reported the filesystem *must not*
        increase the lookup count for the corresponding inodes (even if
        `readdir_reply` returns True).
        """
        self.log.debug("start_id: %s", start_id)
        dir_path = self.data.get_entry(inode).get_full_path()
        self.log.debug("dirpath: %s", dir_path)
        entries = self.data.get_children(inode)
        self.log.debug("items in dir: %d", len(entries))
        try:
            for entry in entries:
                inode = entry.inode
                if inode <= start_id:
                    continue
                node = self.data.nodes[inode]
                self.log.debug("Key: %s, Value_name: %s", inode, entry.name)

                # Omitting swap files.
                if node.type == Types.SWAP:
                    self.log.debug("swp: %s", entry.name)
                    continue
                if node.is_invisible() is True:
                    self.log.debug("Node %s is invisible.", entry.name)
                    continue
                if not pyfuse3.readdir_reply(token, entry.name, await
                                             self.getattr(inode), inode):
                    break
        except Exception as e:
            self.log.error("Readdir failed.")
            self.log.error(e)
        return
Beispiel #17
0
 async def readdir(self, fh, start_id, token):
     # TODO: Could probably implement this with a `DirectoryListing` as well. Class decorator to monkey-patch method from a .listing field?
     logger.trace(f"readdir({fh})")
     if fh == pyfuse3.ROOT_INODE:
         for num, sub in self:
             if num < start_id:
                 continue
             if not pyfuse3.readdir_reply(token, sub.name.encode('utf-8'),
                                          await sub.getattr(sub.root_inode
                                                            ), num + 1):
                 return
     else:
         fuse_assert(fh in self.open_handles)
         inode, deref = self.open_handles[fh]
         # deref() is not None as each SubFS instance is in memory for the life of the program
         return await deref().readdir(inode, start_id, token)
Beispiel #18
0
    async def readdir(self, inode, off, token):
        path = self._inode_to_path(inode)
        log.debug('reading %s', path)
        entries = []
        for name in os.listdir(path):
            if name == '.' or name == '..':
                continue
            attr = self._getattr(path=os.path.join(path, name))
            entries.append((attr.st_ino, name, attr))

        log.debug('read %d entries, starting at %d', len(entries), off)

        for (ino, name, attr) in sorted(entries):
            if ino <= off:
                continue
            if not pyfuse3.readdir_reply(token, fsencode(name), attr, ino):
                break
            self._add_path(attr.st_ino, os.path.join(path, name))
Beispiel #19
0
    async def readdir(self, inode, off, token):
        self.logger.debug("readdir: %s %s", inode, off)

        assert inode == pyfuse3.ROOT_INODE

        filelist = ['.', '..']
        try:
            filelist.extend(self.gridfs.list())
        except:
            raise pyfuse3.FUSEError(errno.ENOTDIR)

        for index, filename in enumerate(itertools.islice(filelist, off, None),
                                         off + 1):
            bname = filename.encode(self._filename_encoding)
            if not pyfuse3.readdir_reply(token, bname, await self.lookup(
                    inode, bname), index):
                break

        return
Beispiel #20
0
 async def readdir(self, vnode, offset, token):
     vinfo_p = self.vm[vnode]
     _opslog.debug('readdir called: {}'.format(vinfo_p.path))
     entries = self._listdir(vinfo_p)
     _opslog.debug('read %d entries, starting at %d', len(entries), offset)
     # FIXME: result is break if entries is changed between two calls to readdir()
     for (ino, name, attr) in sorted(entries):
         if ino <= offset:
             continue
         assert ino in self.vm
         vinfo_c = self.vm[ino]
         want_next_entry = pyfuse3.readdir_reply(token, os.fsencode(name),
                                                 attr, ino)
         if not want_next_entry:
             if vinfo_c.refcount == 0:  # if newly created in the above code
                 del vinfo_c
             break
         # Don't count up reference count if want_next_entry is False
         path_c = self.vm.make_path(vinfo_p.path, name)
         vinfo_c.add_path(path_c)
Beispiel #21
0
    async def readdir(self, id_, off, token):
        log.debug('started with %d, %d', id_, off)
        if off == 0:
            off = -1

        inode = self.inodes[id_]
        if inode.atime_ns < inode.ctime_ns or inode.atime_ns < inode.mtime_ns:
            inode.atime_ns = time_ns()

        # NFS treats offsets 1 and 2 special, so we have to exclude
        # them.
        with self.db.query(
                "SELECT name_id, name, inode FROM contents_v "
                'WHERE parent_inode=? AND name_id > ? ORDER BY name_id',
            (id_, off - 3)) as res:
            for (next_, name, cid_) in res:
                if not pyfuse3.readdir_reply(
                        token, name, self.inodes[cid_].entry_attributes(),
                        next_ + 3):
                    break
                self.open_inodes[cid_] += 1
Beispiel #22
0
 async def readdir(self, vnode, offset, token):
     vinfo_p = self.vm[vnode]
     entries = self._readdir(vinfo_p)
     _opslog.debug('read %d entries, starting at %d', len(entries), offset)
     # FIXME: result is break if entries is changed between two calls to readdir()
     if entries:  # asking empty directory? when?
         assert len(tuple(zip(*entries))[0]) == len(
             set(tuple(zip(*entries))[0]))  # entries must not duplicate
     for ino, name, attr in sorted(entries):
         if ino <= offset:
             continue
         assert ino in self.vm
         vinfo_c = self.vm[ino]
         want_next_entry = pyfuse3.readdir_reply(token, os.fsencode(name),
                                                 attr, ino)
         if not want_next_entry:
             if vinfo_c.refcount == 0:  # if newly created in the above code
                 del vinfo_c
             break
         # Don't count up reference count if want_next_entry is False
         path_c = self.vm.make_path(vinfo_p.path, name)
         vinfo_c.add_path(path_c)
     _acslog.debug('READDIR: {}'.format(vinfo_p.path))
Beispiel #23
0
    async def readdir(self, fh: int, offset: int,
                      token: pyfuse3.ReaddirToken) -> None:
        """ Read entries in an open directory """

        # opendir() uses inode as directory handle
        inode = fh
        direntry = self.inode2entry(inode)
        self.logger.debug("readdir(dirname=%s, fh=%d, offset=%d)",
                          direntry.name, fh, offset)
        assert isinstance(direntry, FuseDirEntry)

        next_id = offset + 1
        try:
            async for entry in direntry.get_entries(offset):
                name = os.fsencode(entry.name)
                attrs = await self.get_attrs(entry)
                if not pyfuse3.readdir_reply(token, name, attrs, next_id):
                    break

                next_id += 1
                self._inode2entry[attrs.st_ino] = entry
        except Exception as err:
            self.logger.exception("Cannot readdir: %s", err)
            raise pyfuse3.FUSEError(errno.ENOENT)
Beispiel #24
0
 async def readdir(self, fh, start_id, token):
     for inode, name in self.listings[fh].list_from(start_id):
         if not pyfuse3.readdir_reply(token, name.encode('utf-8'), await
                                      self.getattr(inode), inode + 1):
             return
Beispiel #25
0
    async def readdir(self, fh, start_id, token):
        #node = self.packages.get_inode(start_id)
        #print('readdir',fh, 'off', start_id)
        if fh == pyfuse3.ROOT_INODE:
            for node in self.packages.pkgs:
                if node.inode <= start_id:
                    continue
                name = f"{node.name}"
                if not pyfuse3.readdir_reply(token, f"{name}".encode(), await self.getattr(node.inode), node.inode):
                    break
        else:
            node = self.packages.get_inode(fh)
            if not node:
                return
            
            DEBUGPKGNAME="vlc"
            if node.name == DEBUGPKGNAME:
                print('  node name', fh, node.name, 'offset:', start_id)
            p = self.packages.handle.get_localdb().get_pkg(node.name)
            offset = fh * 100000
            if start_id >= offset:
                return

            # generate virtual files
            for vfile in Fields:
                offset = (fh * 100000) + vfile.value
                virtual = VirtualFile.factory(vfile.value, node)
                virtual.pkg = p
                if not virtual.readdir_reply(token, await virtual.get_attr(fh, offset), offset):
                    return

            # generate symlinks : Dependencies (and optionals ?)
            # BUG TODO readdir_reply return false after 16 links !!!
            offset += 10
            i = 0 # count bug -> stop always at 17 !!! (vlc, gimp ...)
            for dep in p.depends:
                deps = dep.split('>', 1)
                linknode = self.packages.get_file(deps[:1][0])
                if not linknode:
                    return
                offset += 1
                mode = await self.getattr(linknode.inode)
                mode.st_mode = (stat.S_IFLNK | 0o555)
                mode.st_nlink = linknode.inode
                if node.name == DEBUGPKGNAME:
                    print('  link create dep for:', node.name, offset, 'target:', linknode.name, linknode.inode)
                if not pyfuse3.readdir_reply(token, f"{linknode.name}.dep".encode(), mode, offset):
                    print(dir(token))
                    print(f"ERROR readdir_reply ({i} , {token}) link: {linknode.name} inode: {offset} mode_ino: {mode.st_ino} {mode}")
                    return
                i += 1
            
            if node.name == DEBUGPKGNAME:
                print("optionals:", offset, p.optdepends)
            for dep in p.optdepends:
                if node.name == DEBUGPKGNAME:
                    print(" ? opt:", dep, "->", dep.split(':', 1)[:1][0] )
                linknode = self.packages.get_file(dep.split(':', 1)[:1][0])
                if not linknode:
                    return
                offset += 1
                mode = await self.getattr(linknode.inode)
                mode.st_mode = (stat.S_IFLNK | 0o555)
                mode.st_nlink = linknode.inode
                if node.name == DEBUGPKGNAME:
                    print('  link create opt dep for:', node.name, offset, 'target:', linknode.name, linknode.inode)
                if not pyfuse3.readdir_reply(token, f"{linknode.name}.optional.dep".encode(), mode, offset):
                    print(f"ERROR readdir_reply optional link: {linknode.name} inode: {offset}")
                    return
                #pkg = self.packages.handle.get_localdb().get_pkg(dep)
                
        return
Beispiel #26
0
 def readdir_reply(self, token, datas, inode):
     """ add one entry in package virtual directory """
     return pyfuse3.readdir_reply(token, self.filename.encode(), datas, inode)
Beispiel #27
0
		else:
			entries = ()

		log.debug('read %d entries, starting at %d', len(entries), off)

		# This is not fully posix compatible. If there are hardlinks
		# (two names with the same inode), we don't have a unique
		# offset to start in between them. Note that we cannot simply
		# count entries, because then we would skip over entries
		# (or return them more than once) if the number of directory
		# entries changes between two calls to readdir().
		for (ino, name, attr) in sorted(entries):
			if ino <= off:
				continue
			log.debug(f"{ino} {name}, {attr}")
			if not pyfuse3.readdir_reply(
					token, fsencode(name), attr, ino):
				break
			self._add_path(attr.st_ino, os.path.join(path, name))

	# path methods
	# ============

	async def readlink(self, inode, ctx):
		path = self._inode_to_path(inode)
		try:
			target = os.readlink(path)
		except OSError as exc:
			raise FUSEError(exc.errno)
		return fsencode(target)

	async def link(self, inode, new_inode_p, new_name, ctx):
Beispiel #28
0
 async def readdir(self, fh, start_id, token):
     for row in self.db.get_inodes_from_parent(fh, start_id):
         entry = self._to_entry(row)
         if not pyfuse3.readdir_reply(token, row['name'], entry,
                                      row['link_id']):
             break
Beispiel #29
0
 async def readdir(self, inode, off, token):
     l.debug("readdir: inode=%r, off=%r, token=%r", inode, off, token)
     if off < 1:
         pyfuse3.readdir_reply(token, BASHFS_RUN, await
                               self.lookup(inode, BASHFS_RUN), 1)
     return None
Beispiel #30
0
 async def readdir(self, fh, off, token):
     assert fh == pyfuse3.ROOT_INODE
     if off == 0:
         pyfuse3.readdir_reply(token, self.hello_name, await
                               self.getattr(self.hello_inode), 1)
     return