On python3 using the windows API: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationw
How to get these values (file_system_flags, max_component_length and serial_number), through this function GetVolumeInformationW, without installing any other external modules?
import ctypes
kernel32 = ctypes.windll.kernel32
volumeNameBuffer = ctypes.create_unicode_buffer(1024)
fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
serial_number = None
max_component_length = None
file_system_flags = None
target_disk = 'C:\\'
rc = kernel32.GetVolumeInformationW(
ctypes.c_wchar_p(target_disk),
volumeNameBuffer, ctypes.sizeof(volumeNameBuffer),
serial_number,
max_component_length,
file_system_flags,
fileSystemNameBuffer, ctypes.sizeof(fileSystemNameBuffer)
)
mount_point = target_disk[:-1]
disk_label = volumeNameBuffer.value
fs_type = fileSystemNameBuffer.value
max_length = max_component_length
flags = file_system_flags
serial = serial_number
print(mount_point, disk_label, fs_type, max_length, flags, serial)
Complement: And how do I convert filesystem flags into human readable format?
my_disk_flag = 0x3e706ff
hex_flags = [0x00000002, 0x00000001, 0x20000000, 0x00000010, 0x00040000, 0x00000008, 0x00080000, 0x00100000, 0x00020000, 0x00800000, 0x00400000, 0x00010000, 0x01000000, 0x00000080, 0x00000040, 0x00200000, 0x02000000, 0x00000004, 0x00008000, 0x00000020, 0x08000000]
str_flags = ['FILE_CASE_PRESERVED_NAMES', 'FILE_CASE_SENSITIVE_SEARCH', 'FILE_DAX_VOLUME', 'FILE_FILE_COMPRESSION', 'FILE_NAMED_STREAMS', 'FILE_PERSISTENT_ACLS', 'FILE_READ_ONLY_VOLUME', 'FILE_SEQUENTIAL_WRITE_ONCE', 'FILE_SUPPORTS_ENCRYPTION', 'FILE_SUPPORTS_EXTENDED_ATTRIBUTES', 'FILE_SUPPORTS_HARD_LINKS', 'FILE_SUPPORTS_OBJECT_IDS', 'FILE_SUPPORTS_OPEN_BY_FILE_ID', 'FILE_SUPPORTS_REPARSE_POINTS', 'FILE_SUPPORTS_SPARSE_FILES', 'FILE_SUPPORTS_TRANSACTIONS', 'FILE_SUPPORTS_USN_JOURNAL', 'FILE_UNICODE_ON_DISK', 'FILE_VOLUME_IS_COMPRESSED', 'FILE_VOLUME_QUOTAS', 'FILE_SUPPORTS_BLOCK_REFCOUNTING']
CodePudding user response:
Create an instance of the type and pass it by reference. It is equivalent to declaring a local variable in C and passing its address, e.g. DWORD flags;
and passing as &flags
to be an output parameter.
It also help ctypes error checking by declaring the .argtypes
and .restype
of the function call, which is similar to declaring a C prototype. ctypes.wintypes
has many pre-defined types for Windows.
I've also added an .errcheck
attribute that automatically checks the return value and raises Windows exception based on the GetLastError() code, and an enumeration to process the flags into a readable format:
import ctypes as ct
from ctypes import wintypes as w
from enum import IntFlag
class FSFlags(IntFlag):
FILE_CASE_SENSITIVE_SEARCH = 0x00000001
FILE_CASE_PRESERVED_NAMES = 0x00000002
FILE_UNICODE_ON_DISK = 0x00000004
FILE_PERSISTENT_ACLS = 0x00000008
FILE_FILE_COMPRESSION = 0x00000010
FILE_VOLUME_QUOTAS = 0x00000020
FILE_SUPPORTS_SPARSE_FILES = 0x00000040
FILE_SUPPORTS_REPARSE_POINTS = 0x00000080
FILE_VOLUME_IS_COMPRESSED = 0x00008000
FILE_SUPPORTS_OBJECT_IDS = 0x00010000
FILE_SUPPORTS_ENCRYPTION = 0x00020000
FILE_NAMED_STREAMS = 0x00040000
FILE_READ_ONLY_VOLUME = 0x00080000
FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000
FILE_SUPPORTS_TRANSACTIONS = 0x00200000
FILE_SUPPORTS_HARD_LINKS = 0x00400000
FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000
FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000
FILE_SUPPORTS_USN_JOURNAL = 0x02000000
FILE_SUPPORTS_BLOCK_REFCOUNTING = 0x08000000
FILE_DAX_VOLUME = 0x20000000
def validate(result,func,args):
if not result:
raise ct.WinError(ct.get_last_error())
return None
dll = ct.WinDLL('kernel32',use_last_error=True)
dll.GetVolumeInformationW.argtypes = w.LPCWSTR,w.LPWSTR,w.DWORD,w.LPDWORD,w.LPDWORD,w.LPDWORD,w.LPWSTR,w.DWORD
dll.GetVolumeInformationW.restype = w.BOOL
dll.GetVolumeInformationW.errcheck = validate
volumeNameBuffer = ct.create_unicode_buffer(w.MAX_PATH 1)
fileSystemNameBuffer = ct.create_unicode_buffer(w.MAX_PATH 1)
serial_number = w.DWORD()
max_component_length = w.DWORD()
file_system_flags = w.DWORD()
target_disk = 'c:\\'
dll.GetVolumeInformationW(target_disk,
volumeNameBuffer, ct.sizeof(volumeNameBuffer),
ct.byref(serial_number),
ct.byref(max_component_length),
ct.byref(file_system_flags),
fileSystemNameBuffer, ct.sizeof(fileSystemNameBuffer))
mount_point = target_disk[:-1]
disk_label = volumeNameBuffer.value
fs_type = fileSystemNameBuffer.value
max_length = max_component_length.value
flags = FSFlags(file_system_flags.value)
serial = serial_number.value
print(f'{mount_point=}\n{disk_label=}\n{fs_type=}\n{max_length=}\n{flags=}\n{serial=}')
Output example:
mount_point='c:'
disk_label=''
fs_type='NTFS'
max_length=255
flags=<FSFlags.FILE_SUPPORTS_USN_JOURNAL|FILE_SUPPORTS_OPEN_BY_FILE_ID|FILE_SUPPORTS_EXTENDED_ATTRIBUTES|FILE_SUPPORTS_HARD_LINKS|FILE_SUPPORTS_TRANSACTIONS|FILE_NAMED_STREAMS|FILE_SUPPORTS_ENCRYPTION|FILE_SUPPORTS_OBJECT_IDS|1024|512|FILE_SUPPORTS_REPARSE_POINTS|FILE_SUPPORTS_SPARSE_FILES|FILE_VOLUME_QUOTAS|FILE_FILE_COMPRESSION|FILE_PERSISTENT_ACLS|FILE_UNICODE_ON_DISK|FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH: 65472255>
serial=3465270344
CodePudding user response:
For future reference, I'll leave the complete code here on how to list all disks and get their fstab-like information
import ctypes as ct
import string
from ctypes import wintypes as w
from enum import IntFlag
from pathlib import Path
class FSFlags(IntFlag):
FILE_CASE_SENSITIVE_SEARCH = 0x00000001
FILE_CASE_PRESERVED_NAMES = 0x00000002
FILE_UNICODE_ON_DISK = 0x00000004
FILE_PERSISTENT_ACLS = 0x00000008
FILE_FILE_COMPRESSION = 0x00000010
FILE_VOLUME_QUOTAS = 0x00000020
FILE_SUPPORTS_SPARSE_FILES = 0x00000040
FILE_SUPPORTS_REPARSE_POINTS = 0x00000080
FILE_VOLUME_IS_COMPRESSED = 0x00008000
FILE_SUPPORTS_OBJECT_IDS = 0x00010000
FILE_SUPPORTS_ENCRYPTION = 0x00020000
FILE_NAMED_STREAMS = 0x00040000
FILE_READ_ONLY_VOLUME = 0x00080000
FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000
FILE_SUPPORTS_TRANSACTIONS = 0x00200000
FILE_SUPPORTS_HARD_LINKS = 0x00400000
FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000
FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000
FILE_SUPPORTS_USN_JOURNAL = 0x02000000
FILE_SUPPORTS_BLOCK_REFCOUNTING = 0x08000000
FILE_DAX_VOLUME = 0x20000000
def validate(result,func,args):
if not result:
raise ct.WinError(ct.get_last_error())
return None
dll = ct.WinDLL('kernel32',use_last_error=True)
dll.GetVolumeInformationW.argtypes = w.LPCWSTR,w.LPWSTR,w.DWORD,w.LPDWORD,w.LPDWORD,w.LPDWORD,w.LPWSTR,w.DWORD
dll.GetVolumeInformationW.restype = w.BOOL
dll.GetVolumeInformationW.errcheck = validate
volumeNameBuffer = ct.create_unicode_buffer(w.MAX_PATH 1)
fileSystemNameBuffer = ct.create_unicode_buffer(w.MAX_PATH 1)
serial_number = w.DWORD()
max_component_length = w.DWORD()
file_system_flags = w.DWORD()
lst_available_disks = [f'{d}:\\' for d in string.ascii_uppercase if Path(f'{d}:\\').exists()]
lst_disk_types = ['DRIVE_UNKNOWN', 'DRIVE_NO_ROOT_DIR', 'DRIVE_REMOVABLE', 'DRIVE_FIXED', 'DRIVE_REMOTE', 'DRIVE_CDROM', 'DRIVE_RAMDISK']
for target_disk in lst_available_disks:
disk_type_index = dll.GetDriveTypeW(target_disk)
dll.GetVolumeInformationW(target_disk,
volumeNameBuffer, ct.sizeof(volumeNameBuffer),
ct.byref(serial_number),
ct.byref(max_component_length),
ct.byref(file_system_flags),
fileSystemNameBuffer, ct.sizeof(fileSystemNameBuffer))
mount_point = target_disk
disk_label = volumeNameBuffer.value
fs_type = fileSystemNameBuffer.value
max_length = max_component_length.value
flags = FSFlags(file_system_flags.value)
serial = serial_number.value
if 'FILE_READ_ONLY_VOLUME' in str(flags):
read_write_status = 'ro'
else:
read_write_status = 'rw'
extra_tab_label = ''
if len(disk_label) < 8: extra_tab_label = '\t'
extra_tab_type = ''
if len(lst_disk_types[disk_type_index]) < 12: extra_tab_type = '\t'
print(f'{disk_label}{extra_tab_label}\t{mount_point}\t{fs_type}\t{max_length}\t{serial}\t{read_write_status},{lst_disk_types[disk_type_index]}{extra_tab_type}\t{flags=}\n')
Output (Just replaces disk serial with zeros):
Win10 C:\ NTFS 255 0000000000 rw,DRIVE_FIXED flags=<FSFlags.FILE_SUPPORTS_USN_JOURNAL|FILE_SUPPORTS_OPEN_BY_FILE_ID|FILE_SUPPORTS_EXTENDED_ATTRIBUTES|FILE_SUPPORTS_HARD_LINKS|FILE_SUPPORTS_TRANSACTIONS|FILE_NAMED_STREAMS|FILE_SUPPORTS_ENCRYPTION|FILE_SUPPORTS_OBJECT_IDS|1024|512|FILE_SUPPORTS_REPARSE_POINTS|FILE_SUPPORTS_SPARSE_FILES|FILE_VOLUME_QUOTAS|FILE_FILE_COMPRESSION|FILE_PERSISTENT_ACLS|FILE_UNICODE_ON_DISK|FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH: 65472255>
D:\ FAT32 255 0000000000 rw,DRIVE_FIXED flags=<FSFlags.FILE_SUPPORTS_ENCRYPTION|512|FILE_UNICODE_ON_DISK|FILE_CASE_PRESERVED_NAMES: 131590>
DRV061107 E:\ CDFS 110 0000000000 ro,DRIVE_CDROM flags=<FSFlags.FILE_SUPPORTS_OPEN_BY_FILE_ID|FILE_READ_ONLY_VOLUME|FILE_UNICODE_ON_DISK|FILE_CASE_SENSITIVE_SEARCH: 17301509>
Ventoy F:\ exFAT 255 0000000000 rw,DRIVE_REMOVABLE flags=<FSFlags.FILE_SUPPORTS_ENCRYPTION|512|FILE_UNICODE_ON_DISK|FILE_CASE_PRESERVED_NAMES: 131590>
VTOYEFI G:\ FAT 255 0000000000 rw,DRIVE_REMOVABLE flags=<FSFlags.FILE_SUPPORTS_ENCRYPTION|512|FILE_UNICODE_ON_DISK|FILE_CASE_PRESERVED_NAMES: 131590>