async def getattr(self, inode, ctx=None): """ return file attributes """ if inode > 90000: vinode, _ = self.virtual_inode(inode) return await self.get_virtual_attr(vinode, inode, ctx) entry = pyfuse3.EntryAttributes() if inode < pyfuse3.ROOT_INODE+1: entry.st_mode = (stat.S_IFDIR | 0o555) entry.st_size = 0 stamp = int(time.time() * 1e9) else: node = self.packages.get_inode(inode) if not node: return entry entry.st_mode = node.st_mode entry.st_size = node.st_size stamp = int(node.st_time) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode entry.entry_timeout = 10 entry.attr_timeout = 10 return entry
async def getattr(self, inode, ctx): """ 这个方法需要返回文件或文件夹的基本信息,实际上inode为文件或文件夹的索引节点 因为实现的是网盘文件系统,所以此处虽说物理上不一样,但逻辑上是一样的,在这里我用文件的独立标识fs_id作为inode 根目录没有inode,默认为1,所以此处判断一下如果inode等于根inode的话,直接将返回设置为目录 :param inode: :param ctx: :return: """ entry = pyfuse3.EntryAttributes() entry.generation = 0 entry.entry_timeout = 300 entry.attr_timeout = 300 if inode == pyfuse3.ROOT_INODE: entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_nlink = 0 entry.st_size = 0 else: f = BDFile.get_from_fs_id(inode) entry.st_mode = (stat.S_IFDIR | 0o755) if f.isdir else (stat.S_IFREG | 0o755) entry.st_size = f.size entry.st_nlink = 1 entry.st_atime_ns = int(f.server_mtime * 1e9) entry.st_ctime_ns = int(f.server_ctime * 1e9) entry.st_mtime_ns = int(f.server_mtime * 1e9) inode = f.fs_id entry.st_rdev = 0 entry.st_blksize = 512 entry.st_blocks = 1 entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode return entry
def getattr_sync(self, inode, ctx=None): try: row = self.get_row("SELECT * FROM inodes WHERE id=?", (inode, )) except NoSuchRowError: raise (pyfuse3.FUSEError(errno.ENOENT)) entry = pyfuse3.EntryAttributes() entry.st_ino = inode entry.generation = 0 entry.entry_timeout = 300 entry.attr_timeout = 300 entry.st_mode = row['mode'] entry.st_nlink = self.get_row( "SELECT COUNT(inode) FROM contents WHERE inode=?", (inode, ))[0] entry.st_uid = row['uid'] entry.st_gid = row['gid'] entry.st_rdev = row['rdev'] entry.st_size = row['size'] entry.st_blksize = 512 entry.st_blocks = 1 entry.st_atime_ns = row['atime_ns'] entry.st_mtime_ns = row['mtime_ns'] entry.st_ctime_ns = row['ctime_ns'] return entry
async def getattr(self, inode, ctx=None): self.logger.debug("getattr: %s", inode) if inode == pyfuse3.ROOT_INODE: entry = pyfuse3.EntryAttributes() entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 entry.st_atime_ns = self.root_stamp entry.st_ctime_ns = self.root_stamp entry.st_mtime_ns = self.root_stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode else: file_id = self.inode2id.get(inode) if file_id is None: raise pyfuse3.FUSEError(errno.ENOENT) file_stats = self.gridfs.find_one({'_id': file_id}) if file_stats is None: raise pyfuse3.FUSEError(errno.ENOENT) entry = await self._getattr(file_stats, inode) return entry
def __getattr(self, inode): self.log.debug("get attributes of %i", inode) if inode not in self.data.nodes: self.log.error("Inode not in nodes!") raise FUSEError(errno.ENOENT) node = self.data.nodes[inode] self.data.nodes[inode] = node self.log.debug(self.data.nodes[inode]) self.log.debug(self.data.get_entry(inode)) attr = pyfuse3.EntryAttributes() self.log.debug("MODE in getattr") self.log.debug(node.mode) attr.st_mode = node.mode attr.st_size = node.size attr.st_nlink = 1 + len( self.data.get_entries_of_inode(inode, link_type=LinkTypes.HARDLINK)) attr.st_atime_ns = node.atime attr.st_ctime_ns = node.ctime attr.st_mtime_ns = node.mtime attr.st_gid = node.gid attr.st_uid = node.uid attr.st_ino = inode return attr
def getattr(path=None, fd=None): assert fd is None or path is None assert not (fd is None and path is None) try: if fd is None: # get inode attr stat = os.lstat(path.__str__()) else: stat = os.fstat(fd) except OSError as exc: raise FUSEError(exc.errno) entry = pyfuse3.EntryAttributes() # copy file attributes for attr in ('st_ino', 'st_mode', 'st_nlink', 'st_uid', 'st_gid', 'st_rdev', 'st_size', 'st_atime_ns', 'st_mtime_ns', 'st_ctime_ns'): setattr(entry, attr, getattr( stat, attr)) # more general way of entry.'attr' = stat.'attr' # TODO: probably needs a rework after the NFS is mounted # the inode generation in nfs is not stable after a server restart # src: https://stackoverflow.com/questions/11071996/what-are-inode-generation-numbers entry.generation = 0 # validity of this entry to the kernel # doc-url: https://www.fsl.cs.stonybrook.edu/docs/fuse/fuse-article-appendices.html entry.entry_timeout = float('inf') entry.attr_timeout = float('inf') entry.st_blksize = 512 entry.st_blocks = ((entry.st_size + entry.st_blksize - 1) // entry.st_blksize) return entry
async def _gen_attr(self, entry): attr = pyfuse3.EntryAttributes() attr.st_ino = entry.inode attr.generation = 0 attr.entry_timeout = 10 attr.attr_timeout = 10 attr.st_mode = entry.mode attr.st_nlink = 1 attr.st_uid = entry.uid attr.st_gid = entry.gid attr.st_rdev = 0 attr.st_size = self._get_entry_size(entry) attr.st_blksize = 512 attr.st_blocks = (attr.st_size // attr.st_blksize) + 1 attr.st_atime_ns = entry.atime_ns attr.st_mtime_ns = entry.mtime_ns attr.st_ctime_ns = entry.ctime_ns return attr
def getattr(self) -> pyfuse3.EntryAttributes: entry = pyfuse3.EntryAttributes() if self.paths: try: stat_ = os.lstat(self.path) except OSError as exc: raise pyfuse3.FUSEError(exc.errno) elif self.fds: # file is unlinked already, but opened. try: stat_ = os.fstat(list(self.fds)[0]) except OSError as exc: raise pyfuse3.FUSEError(exc.errno) else: # when? raise RuntimeError() #raise pyfuse3.FUSEError(errno.ENOENT) # No such file or directory # copy attrs from base FS. for attr in ('st_mode', 'st_nlink', 'st_uid', 'st_gid', 'st_rdev', 'st_size', 'st_atime_ns', 'st_mtime_ns', 'st_ctime_ns'): setattr(entry, attr, getattr(stat_, attr)) entry.st_ino = self.vnode entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = ((entry.st_size+entry.st_blksize-1) // entry.st_blksize) return entry
def entry_attributes(self): attr = pyfuse3.EntryAttributes() attr.st_nlink = self.refcount attr.st_blocks = (self.size + 511) // 512 attr.st_ino = self.id # Timeout, can effectively be infinite since attribute changes # are only triggered by the kernel's own requests attr.attr_timeout = 3600 attr.entry_timeout = 3600 # We want our blocksize for IO as large as possible to get large # write requests attr.st_blksize = 128 * 1024 attr.st_mode = self.mode attr.st_uid = self.uid attr.st_gid = self.gid attr.st_size = self.size attr.st_rdev = self.rdev attr.st_atime_ns = self.atime_ns attr.st_mtime_ns = self.mtime_ns attr.st_ctime_ns = self.ctime_ns attr.generation = self.generation return attr
def _getattr(self, info: Inode, ctx: pyfuse3.RequestContext) -> pyfuse3.EntryAttributes: if info.inode() == pyfuse3.ROOT_INODE: is_dir = True else: is_dir = info.is_dir() entry = pyfuse3.EntryAttributes() entry.st_ino = info.inode() entry.generation = 0 entry.entry_timeout = 300 entry.attr_timeout = 300 if is_dir: entry.st_mode = (stat.S_IFDIR | config.MODE_DIR) else: entry.st_mode = (stat.S_IFREG | config.MODE_FILE) entry.st_nlink = 1 entry.st_uid = config.MOUNT_UID entry.st_gid = config.MOUNT_GID entry.st_rdev = 0 entry.st_size = info.size() # entry.st_blksize = config.CHUNKSIZE if is_dir: entry.st_blksize = 1_000_000 else: entry.st_blksize = info.chunk_size() entry.st_blocks = 1 if is_dir else info.chunks_count() entry.st_atime_ns = 0 entry.st_mtime_ns = info.mtime() * 1e6 entry.st_ctime_ns = info.ctime() * 1e6 return entry
async def getattr(self, inode, ctx=None): node = self._get_node(inode) l.debug("getattr: %r", node) entry = pyfuse3.EntryAttributes() entry.st_ino = inode entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 if not node.is_last: entry.st_mode = 0o040777 else: entry.st_mode = 0o100777 entry.st_nlink = 1 entry.st_uid = 1000 entry.st_gid = 1000 entry.st_rdev = 0 if not node.is_last: entry.st_size = 4096 else: entry.st_size = 0 entry.st_blksize = 512 entry.st_blocks = 1 entry.st_atime_ns = 1 entry.st_mtime_ns = 1 entry.st_ctime_ns = 1 return entry
async def getattr(self, inode, ctx=None): logger.debug(f'getattr() called for inode {inode}') entry = pyfuse3.EntryAttributes() if inode in self._inode_to_folder: folder = self._inode_to_folder[inode] # For a folder, we create our own stats entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 # Size of directory is system-defined entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 # TODO: atime is not real entry.st_atime_ns = folder.creation_epoch * 1_000_000_000 entry.st_ctime_ns = folder.creation_epoch * 1_000_000_000 entry.st_mtime_ns = folder.creation_epoch * 1_000_000_000 entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode elif inode in self._inode_to_asset: # This is an asset, we have a file to base all this information on asset = self._inode_to_asset[inode] asset_path = asset.original_path(self.photo_library.path) try: old_stat = os.lstat(asset_path) except OSError as exc: raise FUSEError(exc.errno) # Select the most restrictive mode between readonly and the original file's entry.st_mode = (stat.S_IFREG | (0o644 & old_stat.st_mode)) entry.st_ino = inode for attr in ('st_nlink', 'st_uid', 'st_gid', 'st_rdev', 'st_size'): setattr(entry, attr, getattr(old_stat, attr)) # TODO: atime is not real entry.st_atime_ns = asset.added_epoch * 1_000_000_000 entry.st_ctime_ns = asset.creation_epoch * 1_000_000_000 entry.st_mtime_ns = asset.creation_epoch * 1_000_000_000 entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = ((entry.st_size + entry.st_blksize - 1) // entry.st_blksize) else: raise FUSEError(errno.ENOENT) return entry
async def get_attr(self, inode, offset, ctx=None): entry = pyfuse3.EntryAttributes() entry.st_size = 4000 # less that EntryAttributes.st_blksize 4096 stamp = int(self.node.st_time) entry.st_mode = (stat.S_IFREG | 0o444) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = offset return entry
def _stats2entry(self, s): entry = pyfuse3.EntryAttributes() for attr in ('st_ino', 'st_nlink', 'st_uid', 'st_gid', 'st_rdev', 'st_size', 'st_atime_ns', 'st_mtime_ns', 'st_ctime_ns'): setattr(entry, attr, getattr(s, attr)) entry.st_mode = s.st_mode & ~stat.S_IRWXO & ~stat.S_IRWXG # remove group and world access entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = ((entry.st_size + entry.st_blksize - 1) // entry.st_blksize) return entry
def test_copy(): for obj in (pyfuse3.SetattrFields(), pyfuse3.RequestContext()): pytest.raises(PicklingError, copy, obj) for (inst, attr) in ((pyfuse3.EntryAttributes(), 'st_mode'), (pyfuse3.StatvfsData(), 'f_files')): setattr(inst, attr, 42) inst_copy = copy(inst) assert getattr(inst, attr) == getattr(inst_copy, attr) inst = pyfuse3.FUSEError(10) assert inst.errno == copy(inst).errno
def root_attr(): entry = pyfuse3.EntryAttributes() entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 stamp = int(1438467123.985654 * 1e9) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = pyfuse3.ROOT_INODE return entry
async def get_attrs(self, entry: FuseEntry) -> pyfuse3.EntryAttributes: """ Return entry attributes """ attrs = pyfuse3.EntryAttributes() attrs.st_size = 0 attrs.st_atime_ns = self.time_ns attrs.st_ctime_ns = self.time_ns attrs.st_mtime_ns = self.time_ns attrs.st_gid = self.gid attrs.st_uid = self.uid attrs.st_ino = entry.inode attrs.st_mode = entry.mode attrs.st_size = await entry.size() return attrs
def __makeattr(self, inode, inode_obj): attr = pyfuse3.EntryAttributes() attr.st_ino = inode if inode_obj.size is None: attr.st_mode = S_IFDIR attr.st_size = 0 else: attr.st_mode = S_IFREG attr.st_size = inode_obj.size attr.st_mtime_ns = inode_obj.mtime attr.st_mode |= 0o777 attr.st_uid = 0 attr.st_gid = 0 return attr
def _to_entry(self, row): entry = pyfuse3.EntryAttributes() entry.st_ino = row['id'] entry.st_mode = row['mode'] entry.st_nlink = row['nlink'] entry.st_uid = row['uid'] entry.st_gid = row['gid'] entry.st_rdev = row['rdev'] entry.st_size = row['size'] entry.st_blksize = self.blksize entry.st_blocks = row['nblock'] entry.st_atime_ns = row['atime_ns'] entry.st_mtime_ns = row['mtime_ns'] entry.st_ctime_ns = row['ctime_ns'] return entry
def __init__(self): self.stat = pyfuse3.EntryAttributes() t = time_ns() self.stat.st_atime_ns = t self.stat.st_ctime_ns = t self.stat.st_mtime_ns = t self.stat.st_gid = os.getgid() self.stat.st_uid = os.getuid() self.files = {} self.inodes_created = pyfuse3.ROOT_INODE root = File(b'..', 0, None, True) self.add_file(root)
def _getattr_common(self) -> pyfuse3.EntryAttributes: entry = pyfuse3.EntryAttributes() entry.st_mode = self.filemode entry.st_nlink = 1 entry.st_uid = 0 entry.st_gid = 0 entry.st_rdev = 0 entry.st_size = 0 entry.st_atime_ns = 0 entry.st_mtime_ns = 0 entry.st_ctime_ns = 0 entry.st_ino = self.vnode entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = 0 return entry
def _getattr(self, vinfo): _opslog.debug('getattr path: {}, fd: {}'.format( vinfo.paths, vinfo.fds)) if self._path_mountpoint in vinfo.paths: raise pyfuse3.FUSEError(errno.ENOENT) entry = pyfuse3.EntryAttributes() if vinfo.virtual: entry.st_mode = stat.S_IFREG | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR \ | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP \ | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH entry.st_nlink = 1 entry.st_uid = 0 entry.st_gid = 0 entry.st_rdev = 0 entry.st_size = 0 entry.st_atime_ns = 0 entry.st_mtime_ns = 0 entry.st_ctime_ns = 0 entry.st_ino = vinfo.vnode entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = 0 else: try: stat_ = os.lstat(vinfo.path) except OSError as exc: raise pyfuse3.FUSEError(exc.errno) # copy attrs from base FS. for attr in ('st_mode', 'st_nlink', 'st_uid', 'st_gid', 'st_rdev', 'st_size', 'st_atime_ns', 'st_mtime_ns', 'st_ctime_ns'): setattr(entry, attr, getattr(stat_, attr)) entry.st_ino = vinfo.vnode entry.generation = 0 entry.entry_timeout = 0 entry.attr_timeout = 0 entry.st_blksize = 512 entry.st_blocks = ((entry.st_size + entry.st_blksize - 1) // entry.st_blksize) return entry
async def getattr(self, inode, ctx=None): if inode == pyfuse3.ROOT_INODE: entry = pyfuse3.EntryAttributes() entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 stamp = int(1438467123.985654 * 1e9) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = pyfuse3.ROOT_INODE return entry elif inode in self.files: return self.files[inode].attr else: raise pyfuse3.FUSEError(errno.ENOENT)
def test_rounding(): # Incorrect division previously reaulted in rounding errors for # all dates. entry = pyfuse3.EntryAttributes() secs = 100*365*24*3600 + 999 nanos = _NANOS_PER_SEC - 1 total = secs * _NANOS_PER_SEC + nanos entry.st_atime_ns = total entry.st_ctime_ns = total entry.st_mtime_ns = total # Birthtime skipped -- only valid under BSD and OSX #entry.st_birthtime_ns = total assert entry.st_atime_ns == total assert entry.st_ctime_ns == total assert entry.st_mtime_ns == total
async def getattr(self, inode, ctx=None): """ return file attributes """ #print("getattr", inode) node = self.get_node(inode) if not node: print(" getattrnode ERROR :", node) entry = pyfuse3.EntryAttributes() #if inode < pyfuse3.ROOT_INODE+100: entry.st_mode = (stat.S_IFDIR | 0o555) entry.st_size = 4096 stamp = int(0) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode return entry
async def getattr(self, inode, ctx=None): entry = pyfuse3.EntryAttributes() if inode == pyfuse3.ROOT_INODE: entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 elif inode == self.hello_inode: entry.st_mode = (stat.S_IFREG | 0o644) entry.st_size = len(self.hello_data) else: raise pyfuse3.FUSEError(errno.ENOENT) stamp = int(1438467123.985654 * 1e9) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode return entry
async def getattr(self, inode, ctx=None): entry = pyfuse3.EntryAttributes() if inode == pyfuse3.ROOT_INODE: entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 elif inode == self.hello_inode: entry.st_mode = (stat.S_IFCHR | 0o666) entry.st_size = 0 else: raise pyfuse3.FUSEError(errno.ENOENT) # print(self.stamp) entry.st_atime_ns = self.stamp entry.st_ctime_ns = self.stamp entry.st_mtime_ns = self.stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode return entry
def default_inode_entry(inode) -> pyfuse3.EntryAttributes: """ Caller must set `st_mode` and `st_size` on returned object before it is considered valid. Name? """ entry = pyfuse3.EntryAttributes() # seconds --> nanoseconds stamp = datetime_to_fstime(datetime.now()) entry.st_atime_ns = stamp # accessed entry.st_ctime_ns = stamp # created entry.st_mtime_ns = stamp # modified entry.st_gid = os.getgid() entry.st_uid = os.getuid() entry.st_ino = inode # entry.attr_timeout = 10000 # entry.entry_timeout = 10000 return entry
async def getattr(self, inode, ctx=None): entry = pyfuse3.EntryAttributes() if inode == pyfuse3.ROOT_INODE: entry.st_mode = (stat.S_IFDIR | 0o755) entry.st_size = 0 elif inode in self.files_by_inode: entry.st_mode = (stat.S_IFREG | 0o644) entry.st_size = len(self.files_by_inode[inode].content) else: raise pyfuse3.FUSEError(errno.ENOENT) entry.st_ino = inode stamp = int(1438467123.985654 * 1e9) # WTF # now_ns = int(time() * 1e9) entry.st_atime_ns = stamp entry.st_ctime_ns = stamp entry.st_mtime_ns = stamp entry.st_gid = os.getgid() entry.st_uid = os.getuid() return entry
def _get_degoo_attrs(self, name): element = self._get_degoo_element(name) if not element: raise FUSEError(2) entry = pyfuse3.EntryAttributes() if int(element['ID']) == self._get_id_root_degoo( ) or element['isFolder']: entry.st_size = 0 entry.st_mode = (stat_m.S_IFDIR | 0o755) else: entry.st_size = int(element['Size']) entry.st_mode = (stat_m.S_IFREG | 0o664) entry.st_ino = int(element['ID']) entry.st_uid = os.getuid() entry.st_gid = os.getgid() entry.st_blksize = 512 entry.st_blocks = ((entry.st_size + entry.st_blksize - 1) // entry.st_blksize) timestamp = int(1438467123.985654) try: entry.st_atime_ns = int(element['LastUploadTime']) * 1e9 except KeyError: entry.st_atime_ns = timestamp try: entry.st_ctime_ns = int(element['LastModificationTime']) * 1e9 except KeyError: entry.st_ctime_ns = timestamp try: creation_time = datetime.datetime.fromisoformat( element['CreationTime']) entry.st_mtime_ns = creation_time.timestamp() * 1e9 except KeyError: entry.st_mtime_ns = timestamp return entry