sd_card_info.py 6.21 KB
Newer Older
1 2 3 4
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu

import re
thiolliere's avatar
thiolliere committed
5 6
import sys
import subprocess
7

thiolliere's avatar
thiolliere committed
8
from util import human_readable_size
9
from backend.util import startup_info_args
thiolliere's avatar
thiolliere committed
10

11

thiolliere's avatar
thiolliere committed
12 13 14 15 16
def get_device_index():
    for index, info in enumerate(informations):
        if info["name"] == "device":
            return index

17

18 19 20 21 22
def get_size_index():
    for index, info in enumerate(informations):
        if info["name"] == "size":
            return index

23

thiolliere's avatar
thiolliere committed
24 25 26
if sys.platform == "linux":
    import dbus

27
    visible_informations = 3
thiolliere's avatar
thiolliere committed
28
    informations = [
29 30 31 32 33 34 35 36
        {"name": "device", "typ": str},
        {"name": "formatted_size", "typ": str},
        {"name": "drive_id", "typ": str},
        {"name": "id_label", "typ": str},
        {"name": "id", "typ": str},
        {"name": "drive_connection_bus", "typ": str},
        {"name": "size", "typ": str},
    ]
thiolliere's avatar
thiolliere committed
37

38
    def get_iterator():
thiolliere's avatar
thiolliere committed
39 40
        devices = []
        bus = dbus.SystemBus()
41 42
        udisk = bus.get_object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2")
        udisk_interface = dbus.Interface(udisk, "org.freedesktop.DBus.ObjectManager")
thiolliere's avatar
thiolliere committed
43 44

        for key, value in udisk_interface.GetManagedObjects().items():
45 46 47
            info = value.get("org.freedesktop.UDisks2.Block", {})
            if info.get("IdUsage") == "" and info.get("Drive") != "/":
                device = bytes(info.get("PreferredDevice")).decode("utf-8")
thiolliere's avatar
thiolliere committed
48

49
                size = info.get("Size")
50
                formatted_size = human_readable_size(size, binary=False)
51 52
                devices.append(
                    {
thiolliere's avatar
thiolliere committed
53
                        "key": key,
thiolliere's avatar
thiolliere committed
54 55
                        # Because device name ends with \x00
                        "device": device.replace("\x00", ""),
56 57
                        "size": size,
                        "formatted_size": formatted_size,
58 59 60 61 62
                        "id_label": info.get("IdLabel"),
                        "drive_key": info.get("Drive"),
                        "id": info.get("Id"),
                    }
                )
thiolliere's avatar
thiolliere committed
63 64

        for drive_key, drive_value in udisk_interface.GetManagedObjects().items():
65
            info = drive_value.get("org.freedesktop.UDisks2.Drive", {})
thiolliere's avatar
thiolliere committed
66 67
            for block in devices:
                if drive_key == block["drive_key"]:
68 69 70
                    block["drive_removable"] = info.get("Removable")
                    block["drive_id"] = info.get("Id")
                    block["drive_connection_bus"] = info.get("ConnectionBus")
thiolliere's avatar
thiolliere committed
71

72
        return filter(lambda d: d["drive_removable"] and d["size"] != 0, devices)
thiolliere's avatar
thiolliere committed
73

74

thiolliere's avatar
thiolliere committed
75 76 77
elif sys.platform == "darwin":
    import plistlib

78
    visible_informations = 3
thiolliere's avatar
thiolliere committed
79
    informations = [
80 81 82 83 84 85 86 87 88 89 90
        {"name": "device_identifier", "typ": str},
        {"name": "formatted_size", "typ": str},
        {"name": "io_registry_entry_name", "typ": str},
        {"name": "media_name", "typ": str},
        {"name": "volume_name", "typ": str},
        {"name": "removable", "typ": str},
        {"name": "size", "typ": str},
        {"name": "device", "typ": str},
        {"name": "bus_protocol", "typ": str},
        {"name": "media_type", "typ": str},
    ]
thiolliere's avatar
thiolliere committed
91

92
    def get_iterator():
thiolliere's avatar
thiolliere committed
93 94 95 96 97 98 99 100
        devices = []
        plist = plistlib.loads(subprocess.check_output(["diskutil", "list", "-plist"]))

        device_names = []
        for name in plist["AllDisks"]:
            device_names.extend(re.findall(r"^(disk\d+)$", name))

        for name in device_names:
101 102 103
            plist = plistlib.loads(
                subprocess.check_output(["diskutil", "info", "-plist", name])
            )
104
            size = plist["Size"]
105
            formatted_size = human_readable_size(size, binary=False)
106 107 108 109
            devices.append(
                {
                    "bus_protocol": plist["BusProtocol"],
                    "device_identifier": plist["DeviceIdentifier"],
110
                    "device": plist["DeviceNode"],
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
                    "io_registry_entry_name": plist["IORegistryEntryName"],
                    "media_name": plist["MediaName"],
                    "media_type": plist["MediaType"],
                    "removable": plist["Removable"],
                    "size": size,
                    "formatted_size": formatted_size,
                    "volume_name": plist["VolumeName"],
                }
            )

        return filter(
            lambda d: d["removable"]
            and d["size"] != 0
            and d["bus_protocol"] != "Disk Image",
            devices,
        )

thiolliere's avatar
thiolliere committed
128 129

elif sys.platform == "win32":
130 131

    visible_informations = 3
thiolliere's avatar
thiolliere committed
132
    informations = [
133 134 135 136 137 138 139 140 141
        {"name": "name", "typ": str},
        {"name": "formatted_size", "typ": str},
        {"name": "caption", "typ": str},
        {"name": "description", "typ": str},
        {"name": "media_type", "typ": str},
        {"name": "device", "typ": str},
        {"name": "model", "typ": str},
        {"name": "size", "typ": str},
    ]
thiolliere's avatar
thiolliere committed
142 143

    def extract_field(match, line):
144
        return line[match.start() : match.end()].strip()
thiolliere's avatar
thiolliere committed
145

146
    def get_iterator():
147 148 149 150 151
        lines = (
            subprocess.check_output(["wmic", "diskdrive"], **startup_info_args())
            .decode("utf-8")
            .splitlines()
        )
thiolliere's avatar
thiolliere committed
152 153 154 155

        column = {}
        matches = re.finditer(r"(\w+\W+)", lines[0])
        for match in matches:
156
            column[lines[0][match.start() : match.end()].strip()] = match
thiolliere's avatar
thiolliere committed
157 158 159 160

        devices = []
        lines.pop(0)
        for line in filter(lambda l: len(l) is not 0, lines):
161
            size = extract_field(column["Size"], line)
162
            formatted_size = human_readable_size(size, binary=False)
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
            devices.append(
                {
                    "caption": extract_field(column["Caption"], line),
                    "description": extract_field(column["Description"], line),
                    "device": extract_field(column["DeviceID"], line),
                    "media_type": extract_field(column["MediaType"], line),
                    "model": extract_field(column["Model"], line),
                    "name": extract_field(column["Name"], line),
                    "size": size,
                    "formatted_size": formatted_size,
                }
            )

        return filter(
            lambda d: d["media_type"] != "Fixed hard disk media"
            and d["size"] is not "",
            devices,
        )

thiolliere's avatar
thiolliere committed
182 183 184

else:
    print("platform not supported")
185
    sys.exit(1)