Hi, On 11/10/2009 04:19 PM, Martin Gracik wrote:
Also rewrote the baseudev.py to use the bindings instead of parsing the udev db file --- baseudev.py | 66 ++++++---------------- pyudev.py | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 49 deletions(-) create mode 100644 pyudev.py diff --git a/baseudev.py b/baseudev.py index 76b14cc..978bae0 100644 --- a/baseudev.py +++ b/baseudev.py @@ -23,6 +23,7 @@ import iutil import os +import pyudev import logging log = logging.getLogger("storage") @@ -43,20 +44,24 @@ def udev_get_device(sysfs_path): log.debug("%s does not exist" % sysfs_path) return None - db_entry = sysfs_path.replace("/", "\\x2f") - db_root = "/dev/.udev/db" - db_path = os.path.normpath("%s/%s" % (db_root, db_entry)) - if not os.access(db_path, os.R_OK): - log.debug("db entry %s does not exist" % db_path) - return None + udev = pyudev.Udev() + # XXX we remove the /sys part when enumerating devices, + # so we have to prepend it when creating the device + udev_device = udev.create_device("/sys" + sysfs_path) + udev.teardown() +
Not sure if I like the teardown() name, this implies that after this things can be setup again, which is not true.
+ dev = udev_device.properties + + if dev: + # remove the /dev/ part from beginning of devnode and set as name + dev["name"] = udev_device.devnode[5:] +
This is not correct, this will return mapper/Volgroup-Volname for LV's where it should return just Volgroup-Volname, please find out which libudev function return the actual internal libudev name and use that instead.
+ dev["symlinks"] = dev["DEVLINKS"].split() + dev["sysfs_path"] = sysfs_path - entry = open(db_path).read() - dev = udev_parse_entry(entry) - if dev.has_key("name"): - dev['sysfs_path'] = sysfs_path + # now add in the contents of the uevent file since they're handy dev = udev_parse_uevent_file(dev) - # now add in the contents of the uevent file since they're handy return dev def udev_get_devices(deviceClass="block"): @@ -68,45 +73,8 @@ def udev_get_devices(deviceClass="block"): entries.append(entry) return entries -def udev_parse_entry(buf): - dev = {} - - for line in buf.splitlines(): - line.strip() - (tag, sep, val) = line.partition(":") - if not sep: - continue - - if tag == "N": - dev['name'] = val - elif tag == "S": - if dev.has_key('symlinks'): - dev['symlinks'].append(val) - else: - dev['symlinks'] = [val] - elif tag == "E": - if val.count("=")> 1 and val.count(" ")> 0: - # eg: LVM2_LV_NAME when querying the VG for its LVs - vars = val.split() - vals = [] - var_name = None - for (index, subval) in enumerate(vars): - (var_name, sep, var_val) = subval.partition("=") - if sep: - vals.append(var_val) - - dev[var_name] = vals - else: - (var_name, sep, var_val) = val.partition("=") - if not sep: - continue - - dev[var_name] = var_val - - return dev - def udev_parse_uevent_file(dev): - path = os.path.normpath("/sys/%s/uevent" % dev['sysfs_path']) + path = os.path.normpath("/sys/%s/uevent" % dev["sysfs_path"])
This is a meaningless change, which does not belong in this patch
if not os.access(path, os.R_OK): return dev diff --git a/pyudev.py b/pyudev.py new file mode 100644 index 0000000..8d5a7c2 --- /dev/null +++ b/pyudev.py @@ -0,0 +1,180 @@ +import sys +import os +import fnmatch +from ctypes import * + + +# XXX this one may need some tweaking... +def find_library(name): + libdirs = ("/lib64", "/lib") + + for dir in libdirs: + files = fnmatch.filter(os.listdir(dir), "*%s*" % name) + files = [os.path.join(dir, file) for file in files] + + if files: + break + + if files: + return files[0] + else: + return None +
Please make the matching here less flexible, we want something mathching "lib%s.so.%d" % (name, somajor), where somajor is a new parameter to find_library, this way we can also detect if the ABI ever changes underneed us, as then the somajor will change and we will no longer find the library.
+ +# find the udev library +libudev = find_library("udev") + +if not libudev or not os.path.exists(libudev): + raise ImportError, "No library named %s" % libudev + +# load the udev library +libudev = CDLL(libudev) + + +# create aliases for needed functions and set the return types where needed +libudev_udev_new = libudev.udev_new +libudev_udev_unref = libudev.udev_unref + +libudev_udev_device_new_from_syspath = libudev.udev_device_new_from_syspath +libudev_udev_device_unref = libudev.udev_device_unref + +libudev_udev_device_get_syspath = libudev.udev_device_get_syspath +libudev_udev_device_get_sysname = libudev.udev_device_get_sysname +libudev_udev_device_get_syspath.restype = c_char_p +libudev_udev_device_get_sysname.restype = c_char_p + +libudev_udev_device_get_properties_list_entry = libudev.udev_device_get_properties_list_entry +libudev_udev_list_entry_get_next = libudev.udev_list_entry_get_next + +libudev_udev_list_entry_get_name = libudev.udev_list_entry_get_name +libudev_udev_list_entry_get_value = libudev.udev_list_entry_get_value +libudev_udev_list_entry_get_name.restype = c_char_p +libudev_udev_list_entry_get_value.restype = c_char_p + +libudev_udev_enumerate_new = libudev.udev_enumerate_new +libudev_udev_enumerate_unref = libudev.udev_enumerate_unref + +libudev_udev_enumerate_add_match_subsystem = libudev.udev_enumerate_add_match_subsystem +libudev_udev_enumerate_scan_devices = libudev.udev_enumerate_scan_devices +libudev_udev_enumerate_get_list_entry = libudev.udev_enumerate_get_list_entry + + +class UdevDevice(object): + + def __init__(self, udev, sysfs_path): + self.syspath = None + self.sysname = None + self.properties = {} + + # create new udev device from syspath + udev_device = libudev_udev_device_new_from_syspath(udev, sysfs_path) + if not udev_device: + # device does not exist + return + + # set syspath and sysname properties + self.syspath = libudev_udev_device_get_syspath(udev_device) + self.sysname = libudev_udev_device_get_sysname(udev_device) + + # get the first property entry + property_entry = libudev_udev_device_get_properties_list_entry(udev_device) + + while property_entry: + name = libudev_udev_list_entry_get_name(property_entry) + value = libudev_udev_list_entry_get_value(property_entry) + + # XXX we have to split some of the values into a list, + # the libudev is not so smart :( + fields = value.split() + + if len(fields)> 1: + value = [fields[0]] + + for item in fields[1:]: + (key, sep, val) = item.partition("=") + if sep: + value.append(val) + + if len(value) == 1: + value = value[0] + + self.properties[name] = value + + # get next property entry + property_entry = libudev_udev_list_entry_get_next(property_entry) + + # set additional properties + libudev.udev_device_get_devpath.restype = c_char_p + self.devpath = libudev.udev_device_get_devpath(udev_device) + + libudev.udev_device_get_subsystem.restype = c_char_p + self.subsystem = libudev.udev_device_get_subsystem(udev_device) + + libudev.udev_device_get_devtype.restype = c_char_p + self.devtype = libudev.udev_device_get_devtype(udev_device) + + libudev.udev_device_get_sysnum.restype = c_char_p + self.sysnum = libudev.udev_device_get_sysnum(udev_device) + + libudev.udev_device_get_devnode.restype = c_char_p + self.devnode = libudev.udev_device_get_devnode(udev_device) + + # cleanup + libudev_udev_device_unref(udev_device) + + def __str__(self): + s = "SYSPATH: %s\n" % self.syspath + s += "SYSNAME: %s" % self.sysname + + return s + + +class Udev(object): + + def __init__(self): + self.udev = libudev_udev_new() + + def create_device(self, sysfs_path): + return UdevDevice(self.udev, sysfs_path) + + def scan_devices(self, subsystem=None): + enumerate = libudev_udev_enumerate_new(self.udev) + + # add the match subsystem + if subsystem is not None: + rc = libudev_udev_enumerate_add_match_subsystem(enumerate, subsystem) + if not rc == 0: + print>> sys.stderr, "error: unable to add the match subsystem" + libudev_udev_enumerate_unref(enumerate) + return [] + + # scan the devices + rc = libudev_udev_enumerate_scan_devices(enumerate) + if not rc == 0: + print>> sys.stderr, "error: unable to scan the devices" + libudev_udev_enumerate_unref(enumerate) + return [] + + # create the list of devices + devices = [] + + # get the first device entry + device_entry = libudev_udev_enumerate_get_list_entry(enumerate) + + while device_entry: + sysfs_path = libudev_udev_list_entry_get_name(device_entry) + device = self.create_device(sysfs_path) + + if device.syspath is not None: + devices.append(device) + + # get next device entry + device_entry = libudev_udev_list_entry_get_next(device_entry) + + # cleanup + libudev_udev_enumerate_unref(enumerate) + + return devices + + def teardown(self): + libudev_udev_unref(self.udev)
You will want to set self.udev to None after this, and check all other uses for it to be not None, other wise you may cause a segfault (referring freed memory) ! Regards, Hana _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list