Coverage for linuxpy/statfs.py: 76%

36 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-10-18 07:40 +0200

1# 

2# This file is part of the linuxpy project 

3# 

4# Copyright (c) 2023 Tiago Coutinho 

5# Distributed under the GPLv3 license. See LICENSE for more info. 

6 

7import enum 

8import functools 

9 

10from .ctypes import ( 

11 POINTER, 

12 Struct, 

13 c, 

14 ccharp, 

15 cint, 

16 cuint, 

17 culong, 

18 fsblkcnt, 

19 fsfilcnt, 

20 pointer, 

21) 

22from .magic import Magic 

23 

24 

25class fsid(Struct): 

26 _fields_ = [("val", cint * 2)] 

27 

28 

29class statfs(Struct): 

30 _fields_ = [ 

31 ("f_type", cuint), # Type of filesystem (see below) 

32 ("f_bsize", cuint), # Optimal transfer block size 

33 ("f_blocks", fsblkcnt), # Total data blocks in filesystem 

34 ("f_bfree", fsblkcnt), # Free blocks in filesystem 

35 ("f_bavail", fsblkcnt), # Free blocks available to unprivileged user 

36 ("f_files", fsfilcnt), # Total file nodes in filesystem 

37 ("f_ffree", fsfilcnt), # Free file nodes in filesystem 

38 ("f_fsid", fsid), # Filesystem ID 

39 ("f_namelen", cuint), # Maximum length of filenames 

40 ("f_frsize", cuint), # Fragment size (since Linux 2.6) 

41 ("f_flags", cuint), # Mount flags of filesystem (since Linux 2.6.36) 

42 # Setting f_spare to 4 * int was giving me segfault 

43 ("f_spare", cuint * 16), # Padding bytes reserved for future use 

44 ] 

45 

46 

47class statvfs(Struct): 

48 _fields_ = [ 

49 ("f_bsize", culong), # Filesystem block size 

50 ("f_frsize", culong), # Fragment size 

51 ("f_blocks", fsblkcnt), # Size of fs in f_frsize units 

52 ("f_bfree", fsblkcnt), # Number of free blocks 

53 ("f_bavail", fsblkcnt), # Number of free blocks for unprivileged user 

54 ("f_files", fsfilcnt), # Number of inodes 

55 ("f_ffree", fsfilcnt), # Number of free inodes 

56 ("f_favail", fsfilcnt), # Number of free inodes for unprivileged user 

57 ("f_fsid", culong), # Filesystem ID 

58 ("f_flag", culong), # Mount flags 

59 ("f_namemax", culong), # Maximum filename length 

60 ] 

61 

62 

63class Flag(enum.IntFlag): 

64 RDONLY = 0x0001 # mount read-only 

65 NOSUID = 0x0002 # ignore suid and sgid bits 

66 NODEV = 0x0004 # disallow access to device special files 

67 NOEXEC = 0x0008 # disallow program execution 

68 SYNCHRONOUS = 0x0010 # writes are synced at once 

69 VALID = 0x0020 # f_flags support is implemented 

70 MANDLOCK = 0x0040 # allow mandatory locks on an FS 

71 # 0x0080 used for ST_WRITE in glibc 

72 # 0x0100 used for ST_APPEND in glibc 

73 # 0x0200 used for ST_IMMUTABLE in glibc 

74 NOATIME = 0x0400 # do not update access times 

75 NODIRATIME = 0x0800 # do not update directory access times 

76 RELATIME = 0x1000 # update atime relative to mtime/ctime 

77 NOSYMFOLLOW = 0x2000 # do not follow symlinks 

78 

79 

80c.statfs.argtypes = [ccharp, POINTER(statfs)] 

81c.statfs.restype = cint 

82 

83c.statvfs.argtypes = [ccharp, POINTER(statvfs)] 

84c.statvfs.restype = cint 

85 

86 

87def get_statfs_raw(path) -> statfs: 

88 if not isinstance(path, (bytes, ccharp)): 

89 path = str(path).encode() 

90 result = statfs() 

91 c.statfs(path, pointer(result)) 

92 return result 

93 

94 

95@functools.lru_cache 

96def get_fs_type(path) -> Magic: 

97 ftype = get_statfs_raw(path).f_type 

98 return None if not ftype else Magic(ftype)