usb-ks

USB Killswitch
git clone git://git.laack.co/usb-ks.git
Log | Files | Refs | README | LICENSE

enumerate.go (8994B)


      1 // +build linux,cgo
      2 
      3 package udev
      4 
      5 /*
      6   #cgo LDFLAGS: -ludev
      7   #include <libudev.h>
      8   #include <linux/types.h>
      9   #include <stdlib.h>
     10 	#include <linux/kdev_t.h>
     11 */
     12 import "C"
     13 
     14 import (
     15 	"errors"
     16 
     17 	"github.com/jkeiser/iter"
     18 )
     19 
     20 // Enumerate is an opaque struct wrapping a udev enumerate object.
     21 type Enumerate struct {
     22 	ptr *C.struct_udev_enumerate
     23 	u   *Udev
     24 }
     25 
     26 // Lock the udev context
     27 func (e *Enumerate) lock() {
     28 	e.u.m.Lock()
     29 }
     30 
     31 // Unlock the udev context
     32 func (e *Enumerate) unlock() {
     33 	e.u.m.Unlock()
     34 }
     35 
     36 // Unref the Enumerate object
     37 func enumerateUnref(e *Enumerate) {
     38 	C.udev_enumerate_unref(e.ptr)
     39 }
     40 
     41 // AddMatchSubsystem adds a filter for a subsystem of the device to include in the list.
     42 func (e *Enumerate) AddMatchSubsystem(subsystem string) (err error) {
     43 	e.lock()
     44 	defer e.unlock()
     45 	s := C.CString(subsystem)
     46 	defer freeCharPtr(s)
     47 	if C.udev_enumerate_add_match_subsystem(e.ptr, s) != 0 {
     48 		err = errors.New("udev: udev_enumerate_add_match_subsystem failed")
     49 	}
     50 	return
     51 }
     52 
     53 // AddNomatchSubsystem adds a filter for a subsystem of the device to exclude from the list.
     54 func (e *Enumerate) AddNomatchSubsystem(subsystem string) (err error) {
     55 	e.lock()
     56 	defer e.unlock()
     57 	s := C.CString(subsystem)
     58 	defer freeCharPtr(s)
     59 	if C.udev_enumerate_add_nomatch_subsystem(e.ptr, s) != 0 {
     60 		err = errors.New("udev: udev_enumerate_add_nomatch_subsystem failed")
     61 	}
     62 	return
     63 }
     64 
     65 // AddMatchSysattr adds a filter for a sys attribute at the device to include in the list.
     66 func (e *Enumerate) AddMatchSysattr(sysattr, value string) (err error) {
     67 	e.lock()
     68 	defer e.unlock()
     69 	s, v := C.CString(sysattr), C.CString(value)
     70 	defer freeCharPtr(s)
     71 	defer freeCharPtr(v)
     72 	if C.udev_enumerate_add_match_sysattr(e.ptr, s, v) != 0 {
     73 		err = errors.New("udev: udev_enumerate_add_match_sysattr failed")
     74 	}
     75 	return
     76 }
     77 
     78 // AddNomatchSysattr adds a filter for a sys attribute at the device to exclude from the list.
     79 func (e *Enumerate) AddNomatchSysattr(sysattr, value string) (err error) {
     80 	e.lock()
     81 	defer e.unlock()
     82 	s, v := C.CString(sysattr), C.CString(value)
     83 	defer freeCharPtr(s)
     84 	defer freeCharPtr(v)
     85 	if C.udev_enumerate_add_nomatch_sysattr(e.ptr, s, v) != 0 {
     86 		err = errors.New("udev: udev_enumerate_add_nomatch_sysattr failed")
     87 	}
     88 	return
     89 }
     90 
     91 // AddMatchProperty adds a filter for a property of the device to include in the list.
     92 func (e *Enumerate) AddMatchProperty(property, value string) (err error) {
     93 	e.lock()
     94 	defer e.unlock()
     95 	p, v := C.CString(property), C.CString(value)
     96 	defer freeCharPtr(p)
     97 	defer freeCharPtr(v)
     98 	if C.udev_enumerate_add_match_property(e.ptr, p, v) != 0 {
     99 		err = errors.New("udev: udev_enumerate_add_match_property failed")
    100 	}
    101 	return
    102 }
    103 
    104 // AddMatchSysname adds a filter for the name of the device to include in the list.
    105 func (e *Enumerate) AddMatchSysname(sysname string) (err error) {
    106 	e.lock()
    107 	defer e.unlock()
    108 	s := C.CString(sysname)
    109 	defer freeCharPtr(s)
    110 	if C.udev_enumerate_add_match_sysname(e.ptr, s) != 0 {
    111 		err = errors.New("udev: udev_enumerate_add_match_sysname failed")
    112 	}
    113 	return
    114 }
    115 
    116 // AddMatchTag adds a filter for a tag of the device to include in the list.
    117 func (e *Enumerate) AddMatchTag(tag string) (err error) {
    118 	e.lock()
    119 	defer e.unlock()
    120 	t := C.CString(tag)
    121 	defer freeCharPtr(t)
    122 	if C.udev_enumerate_add_match_tag(e.ptr, t) != 0 {
    123 		err = errors.New("udev: udev_enumerate_add_match_tag failed")
    124 	}
    125 	return
    126 }
    127 
    128 // AddMatchParent adds a filter for a parent Device to include in the list.
    129 func (e *Enumerate) AddMatchParent(parent *Device) (err error) {
    130 	e.lock()
    131 	defer e.unlock()
    132 	if C.udev_enumerate_add_match_parent(e.ptr, parent.ptr) != 0 {
    133 		err = errors.New("udev: udev_enumerate_add_match_parent failed")
    134 	}
    135 	return
    136 }
    137 
    138 // AddMatchIsInitialized adds a filter matching only devices which udev has set up already.
    139 // This makes sure, that the device node permissions and context are properly set and that network devices are fully renamed.
    140 // Usually, devices which are found in the kernel but not already handled by udev, have still pending events.
    141 // Services should subscribe to monitor events and wait for these devices to become ready, instead of using uninitialized devices.
    142 // For now, this will not affect devices which do not have a device node and are not network interfaces.
    143 func (e *Enumerate) AddMatchIsInitialized() (err error) {
    144 	e.lock()
    145 	defer e.unlock()
    146 	if C.udev_enumerate_add_match_is_initialized(e.ptr) != 0 {
    147 		err = errors.New("udev: udev_enumerate_add_match_is_initialized failed")
    148 	}
    149 	return
    150 }
    151 
    152 // AddSyspath adds a device to the list of enumerated devices, to retrieve it back sorted in dependency order.
    153 func (e *Enumerate) AddSyspath(syspath string) (err error) {
    154 	e.lock()
    155 	defer e.unlock()
    156 	s := C.CString(syspath)
    157 	defer freeCharPtr(s)
    158 	if C.udev_enumerate_add_syspath(e.ptr, s) != 0 {
    159 		err = errors.New("udev: udev_enumerate_add_syspath failed")
    160 	}
    161 	return
    162 }
    163 
    164 // DeviceSyspaths retrieves a list of device syspaths matching the filter, sorted in dependency order.
    165 func (e *Enumerate) DeviceSyspaths() (s []string, err error) {
    166 	e.lock()
    167 	defer e.unlock()
    168 	if C.udev_enumerate_scan_devices(e.ptr) < 0 {
    169 		err = errors.New("udev: udev_enumerate_scan_devices failed")
    170 	} else {
    171 		s = make([]string, 0)
    172 		for l := C.udev_enumerate_get_list_entry(e.ptr); l != nil; l = C.udev_list_entry_get_next(l) {
    173 			s = append(s, C.GoString(C.udev_list_entry_get_name(l)))
    174 		}
    175 	}
    176 	return
    177 }
    178 
    179 // DeviceSyspathIterator returns an Iterator over the device syspaths matching the filter, sorted in dependency order.
    180 // The Iterator is using the github.com/jkeiser/iter package.
    181 // Values are returned as an interface{} and should be cast to string.
    182 func (e *Enumerate) DeviceSyspathIterator() (it iter.Iterator, err error) {
    183 	e.lock()
    184 	defer e.unlock()
    185 	if C.udev_enumerate_scan_devices(e.ptr) < 0 {
    186 		err = errors.New("udev: udev_enumerate_scan_devices failed")
    187 	} else {
    188 		l := C.udev_enumerate_get_list_entry(e.ptr)
    189 		it = iter.Iterator{
    190 			Next: func() (item interface{}, err error) {
    191 				e.lock()
    192 				defer e.unlock()
    193 				if l != nil {
    194 					item = C.GoString(C.udev_list_entry_get_name(l))
    195 					l = C.udev_list_entry_get_next(l)
    196 				} else {
    197 					err = iter.FINISHED
    198 				}
    199 				return
    200 			},
    201 			Close: func() {
    202 			},
    203 		}
    204 	}
    205 	return
    206 }
    207 
    208 // SubsystemSyspaths retrieves a list of subsystem syspaths matching the filter, sorted in dependency order.
    209 func (e *Enumerate) SubsystemSyspaths() (s []string, err error) {
    210 	e.lock()
    211 	defer e.unlock()
    212 	if C.udev_enumerate_scan_subsystems(e.ptr) < 0 {
    213 		err = errors.New("udev: udev_enumerate_scan_subsystems failed")
    214 	} else {
    215 		s = make([]string, 0)
    216 		for l := C.udev_enumerate_get_list_entry(e.ptr); l != nil; l = C.udev_list_entry_get_next(l) {
    217 			s = append(s, C.GoString(C.udev_list_entry_get_name(l)))
    218 		}
    219 	}
    220 	return
    221 }
    222 
    223 // DeviceSubsystemIterator returns an Iterator over the subsystem syspaths matching the filter, sorted in dependency order.
    224 // The Iterator is using the github.com/jkeiser/iter package.
    225 // Values are returned as an interface{} and should be cast to string.
    226 func (e *Enumerate) DeviceSubsystemIterator() (it iter.Iterator, err error) {
    227 	e.lock()
    228 	defer e.unlock()
    229 	if C.udev_enumerate_scan_subsystems(e.ptr) < 0 {
    230 		err = errors.New("udev: udev_enumerate_scan_devices failed")
    231 	} else {
    232 		l := C.udev_enumerate_get_list_entry(e.ptr)
    233 		it = iter.Iterator{
    234 			Next: func() (item interface{}, err error) {
    235 				e.lock()
    236 				defer e.unlock()
    237 				if l != nil {
    238 					item = C.GoString(C.udev_list_entry_get_name(l))
    239 					l = C.udev_list_entry_get_next(l)
    240 				} else {
    241 					err = iter.FINISHED
    242 				}
    243 				return
    244 			},
    245 			Close: func() {
    246 			},
    247 		}
    248 	}
    249 	return
    250 }
    251 
    252 // Devices retrieves a list of Devices matching the filter, sorted in dependency order.
    253 func (e *Enumerate) Devices() (m []*Device, err error) {
    254 	e.lock()
    255 	defer e.unlock()
    256 	if C.udev_enumerate_scan_devices(e.ptr) < 0 {
    257 		err = errors.New("udev: udev_enumerate_scan_devices failed")
    258 	} else {
    259 		m = make([]*Device, 0)
    260 		for l := C.udev_enumerate_get_list_entry(e.ptr); l != nil; l = C.udev_list_entry_get_next(l) {
    261 			s := C.udev_list_entry_get_name(l)
    262 			m = append(m, e.u.newDevice(C.udev_device_new_from_syspath(e.u.ptr, s)))
    263 		}
    264 	}
    265 	return
    266 }
    267 
    268 // DeviceIterator returns an Iterator over the Devices matching the filter, sorted in dependency order.
    269 // The Iterator is using the github.com/jkeiser/iter package.
    270 // Values are returned as an interface{} and should be cast to *Device.
    271 func (e *Enumerate) DeviceIterator() (it iter.Iterator, err error) {
    272 	e.lock()
    273 	defer e.unlock()
    274 	if C.udev_enumerate_scan_devices(e.ptr) < 0 {
    275 		err = errors.New("udev: udev_enumerate_scan_devices failed")
    276 	} else {
    277 		l := C.udev_enumerate_get_list_entry(e.ptr)
    278 		it = iter.Iterator{
    279 			Next: func() (item interface{}, err error) {
    280 				e.lock()
    281 				defer e.unlock()
    282 				if l != nil {
    283 					s := C.udev_list_entry_get_name(l)
    284 					item = e.u.newDevice(C.udev_device_new_from_syspath(e.u.ptr, s))
    285 					l = C.udev_list_entry_get_next(l)
    286 				} else {
    287 					err = iter.FINISHED
    288 				}
    289 				return
    290 			},
    291 			Close: func() {
    292 			},
    293 		}
    294 	}
    295 	return
    296 }