Read from SysFS

    :param key: file or path in SysFS; if key is a list then root will be prefixed on each key

    :return: the full (tree of) SysFS attributes under key

    CLI example:
     .. code-block:: bash

        salt '*' sysfs.read class/net/em1/statistics

def read(key, root=''):
    '''
    Read from SysFS

    :param key: file or path in SysFS; if key is a list then root will be prefixed on each key

    :return: the full (tree of) SysFS attributes under key

    CLI example:
     .. code-block:: bash

        salt '*' sysfs.read class/net/em1/statistics
    '''

    if not isinstance(key, six.string_types):
        res = {}
        for akey in key:
            ares = read(os.path.join(root, akey))
            if ares is not False:
                res[akey] = ares
        return res

    key = target(os.path.join(root, key))
    if key is False:
        return False
    elif os.path.isdir(key):
        keys = interfaces(key)
        result = {}
        for subkey in keys['r'] + keys['rw']:
            subval = read(os.path.join(key, subkey))
            if subval is not False:
                subkeys = subkey.split('/')
                subkey = subkeys.pop()
                subresult = result
                if subkeys:
                    for skey in subkeys:
                        if skey not in subresult:
                            subresult[skey] = {}
                        subresult = subresult[skey]
                subresult[subkey] = subval
        return result
    else:
        try:
            log.trace('Reading %s...', key)

            # Certain things in SysFS are pipes 'n such.
            # This opens it non-blocking, which prevents indefinite blocking
            with os.fdopen(os.open(key, os.O_RDONLY | os.O_NONBLOCK)) as treader:
                # alternative method for the same idea, but only works for completely empty pipes
                # treader = select.select([treader], [], [], 1)[0][0]
                val = treader.read().strip()
                if not val:
                    return False
                try:
                    val = int(val)
                except Exception:
                    try:
                        val = float(val)
                    except Exception:
                        pass
                return val
        except Exception:
            return False