Skip to content

Commit

Permalink
Report filesystem usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Eeems committed Jan 3, 2024
1 parent 9d2a0e0 commit 690a3eb
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 55 deletions.
49 changes: 40 additions & 9 deletions remarkable_update_fuse/ext4/blockdescriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,66 @@ def __init__(self, volume, offset, bg_no):

@property
def bg_block_bitmap(self):
return self.bg_block_bitmap_hi << 32 | self.bg_block_bitmap_lo
if self.volume.has_hi:
return self.bg_block_bitmap_hi << 32 | self.bg_block_bitmap_lo

return self.bg_block_bitmap_lo

@property
def bg_inode_bitmap(self):
return self.bg_inode_bitmap_hi << 32 | self.bg_inode_bitmap_lo
if self.volume.has_hi:
return self.bg_inode_bitmap_hi << 32 | self.bg_inode_bitmap_lo

return self.bg_inode_bitmap_lo

@property
def bg_free_blocks_count(self):
return self.bg_free_blocks_count_hi << 32 | self.bg_free_blocks_count_lo
if self.volume.has_hi:
return self.bg_free_blocks_count_hi << 32 | self.bg_free_blocks_count_lo

return self.bg_free_blocks_count_lo

@property
def bg_free_inodes_count(self):
return self.bg_free_inodes_count_hi << 32 | self.bg_free_inodes_count_lo
if self.volume.has_hi:
return self.bg_free_inodes_count_hi << 32 | self.bg_free_inodes_count_lo

return self.bg_free_inodes_count_lo

@property
def bg_exclude_bitmap(self):
return self.bg_exclude_bitmap_hi << 32 | self.bg_exclude_bitmap_lo
if self.volume.has_hi:
return self.bg_exclude_bitmap_hi << 32 | self.bg_exclude_bitmap_lo

return self.bg_exclude_bitmap_lo

@property
def bg_used_dirs_count(self):
return self.bg_used_dirs_count_hi << 32 | self.bg_used_dirs_count_lo
if self.volume.has_hi:
return self.bg_used_dirs_count_hi << 32 | self.bg_used_dirs_count_lo

return self.bg_used_dirs_count_lo

@property
def bg_block_bitmap_csum(self):
return self.bg_block_bitmap_csum_hi << 32 | self.bg_block_bitmap_csum_lo
if self.volume.has_hi:
return self.bg_block_bitmap_csum_hi << 32 | self.bg_block_bitmap_csum_lo

return self.bg_block_bitmap_csum_lo

@property
def bg_inode_bitmap_csum(self):
return self.bg_inode_bitmap_csum_hi << 32 | self.bg_inode_bitmap_csum_lo
if self.volume.has_hi:
return self.bg_inode_bitmap_csum_hi << 32 | self.bg_inode_bitmap_csum_lo

return self.bg_inode_bitmap_csum_lo

@property
def bg_itable_unused(self):
return self.bg_itable_unused_hi << 32 | self.bg_itable_unused_lo
if self.volume.has_hi:
return self.bg_itable_unused_hi << 32 | self.bg_itable_unused_lo

return self.bg_itable_unused_lo

@property
def bg_inode_table(self):
Expand All @@ -82,6 +109,10 @@ def bg_inode_table(self):

return self.bg_inode_table_lo

@property
def superblock(self):
return self.volume.superblock

@property
def checksum(self):
csum = crc32c(self.bg_no.to_bytes(4, "little"), self.volume.seed)
Expand Down
26 changes: 26 additions & 0 deletions remarkable_update_fuse/ext4/superblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,32 @@ def __init__(self, volume, _=None):
def has_hi(self):
return (self.s_feature_incompat & EXT4_FEATURE_INCOMPAT.IS64BIT) != 0

@property
def s_blocks_count(self):
return (
(self.s_blocks_per_group) * len(self.volume.group_descriptors)
- self.s_reserved_gdt_blocks
- self.s_overhead_blocks
)
# if self.has_hi:
# return self.s_blocks_count_hi << 32 | self.s_blocks_count_lo

# return self.s_blocks_count_lo

@property
def s_r_blocks_count(self):
if self.has_hi:
return self.s_r_blocks_count_hi << 32 | self.s_r_blocks_count_lo

return self.s_r_blocks_count_lo

@property
def s_free_blocks_count(self):
if self.has_hi:
return self.s_free_blocks_count_hi << 32 | self.s_free_blocks_count_lo

return self.s_free_blocks_count_lo

@property
def expected_magic(self):
return 0xEF53
Expand Down
136 changes: 103 additions & 33 deletions remarkable_update_fuse/fuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,66 +211,136 @@ def get_inode(self, path):

return inode

def getattr(self, path):
try:
inode = self.get_inode(path)
_stat = Stat()
_stat.st_mode = inode.i_mode.value
_stat.st_ino = inode.i_uid
_stat.st_nlink = inode.i_links_count
_stat.st_uid = inode.i_uid
_stat.st_gid = inode.i_gid
_stat.st_size = inode.i_size
_stat.st_atime = inode.i_atime
_stat.st_mtime = inode.i_mtime
_stat.st_ctime = inode.i_ctime
return _stat
except FileNotFoundError:
return -errno.ENOENT
def statfs(self):
superblock = self.volume.superblock
struct = fuse.StatVfs()
struct.f_bsize = self.volume.block_size
struct.f_frsize = self.volume.block_size
struct.f_blocks = superblock.s_blocks_count
struct.f_bfree = superblock.s_free_blocks_count
struct.f_bavail = superblock.s_free_blocks_count - superblock.s_r_blocks_count
struct.f_files = superblock.s_inodes_count
struct.f_ffree = superblock.s_free_inodes_count
struct.f_favail = superblock.s_free_inodes_count
struct.f_flag = superblock.s_flags.value
struct.f_namemax = ext4.EXT4_NAME_LEN
return struct

def getattr(self, path, inode=None):
if inode is None:
try:
inode = self.get_inode(path)

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

_stat = Stat()
_stat.st_mode = inode.i_mode.value
_stat.st_ino = inode.i_uid
_stat.st_nlink = inode.i_links_count
_stat.st_uid = inode.i_uid
_stat.st_gid = inode.i_gid
_stat.st_size = inode.i_size
_stat.st_atime = inode.i_atime
_stat.st_mtime = inode.i_mtime
_stat.st_ctime = inode.i_ctime
return _stat

def readdir(self, path, _):
def open(self, path, flags):
try:
inode = self.get_inode(path)
for dirent, _ in inode.opendir():
yield fuse.Direntry(dirent.name_str)
if isinstance(inode, ext4.Directory):
return -errno.EACCES

mode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
if (flags & mode) != os.O_RDONLY:
return -errno.EACCES

return inode

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

def open(self, path, flags):
def release(self, _, __=None):
return

def read(self, path, size, offset, inode=None):
if inode is None:
try:
inode = self.get_inode(path)

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

reader = inode.open()
reader.seek(offset, os.SEEK_SET)
return reader.read(size)

def readlink(self, path, inode=None):
if inode is None:
try:
inode = self.get_inode(path)

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

if not isinstance(inode, ext4.SymbolicLink):
return path

return inode.readlink().decode("utf-8")

def getxattr(self, path, name, _):
try:
inode = self.get_inode(path)
if isinstance(inode, ext4.Directory):
return -errno.EACCES
for _name, value in inode.xattrs:
if _name == name:
return value

mode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
if (flags & mode) != os.O_RDONLY:
return -errno.EACCES
return None

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

def read(self, path, size, offset):
def listxattr(self, path, _):
try:
inode = self.get_inode(path)
reader = inode.open()
reader.seek(offset, os.SEEK_SET)
return reader.read(size)
for name, _ in inode.xattrs:
yield name

return None

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

def readlink(self, path):
def opendir(self, path):
try:
inode = self.get_inode(path)
if not isinstance(inode, ext4.SymbolicLink):
return path
if not isinstance(inode, ext4.Directory):
return -errno.EACCES

return inode.readlink().decode("utf-8")
return inode

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

def releasedir(self, _, __=None):
return

def readdir(self, path, _, inode=None):
if inode is None:
try:
inode = self.get_inode(path)

except FileNotFoundError:
print(f"{path} not found")
return -errno.ENOENT

for dirent, _ in inode.opendir():
yield fuse.Direntry(dirent.name_str)
Loading

0 comments on commit 690a3eb

Please sign in to comment.