Exemple #1
0
def fgetattr(filename, compact=False):
    """Get the list of set system attributes for file specified by 'path'.
    Returns a list of verbose attributes by default. If 'compact' is True,
    return a string consisting of compact option identifiers."""

    from pkg.misc import force_text
    if not isinstance(filename, six.string_types):
        raise TypeError("filename must be string type")

    cattrs = ffi.new("char[F_ATTR_ALL]")
    response = ffi.new("nvlist_t **")
    # ffi.gc return a new cdata object that points to the same data. Later,
    # when this new cdata object is garbage-collected, the destructor
    # (in this case 'lib.nvlist_free' will be called.
    response[0] = ffi.gc(response[0], lib.nvlist_free)
    bval = ffi.new("boolean_t *")
    pair = ffi.NULL
    next_pair = ffi.new("nvpair_t *")
    attr_list = []

    fd = os.open(filename, os.O_RDONLY)
    if fd == -1:
        raise OSError(ffi.errno, os.strerror(ffi.errno), filename)

    if lib.fgetattr(fd, lib.XATTR_VIEW_READWRITE, response):
        os.close(fd)
        raise OSError(ffi.errno, os.strerror(ffi.errno), filename)
    os.close(fd)

    count = 0
    pair = lib.nvlist_next_nvpair(response[0], pair)
    while pair != ffi.NULL:
        name = lib.nvpair_name(pair)
        next_pair = lib.nvlist_next_nvpair(response[0], pair)
        # we ignore all non-boolean attrs
        if lib.nvpair_type(pair) != lib.DATA_TYPE_BOOLEAN_VALUE:
            pair = next_pair
            continue

        if lib.nvpair_value_boolean_value(pair, bval) != 0:
            raise OSError("could not read attr value")

        if bval[0]:
            if compact:
                if count >= F_ATTR_ALL:
                    raise OSError("Too many system attributes found")
                cattrs[count] = lib.attr_to_option(lib.name_to_attr(name))[0]
                count += 1
            else:
                # ffi.string returns a bytes
                string = force_text(ffi.string(name))
                if string:
                    attr_list.append(string)
        pair = next_pair

    if compact:
        cattrs = force_text(ffi.string(cattrs))
        return cattrs
    return attr_list
Exemple #2
0
def fsetattr(filename, attr):
    """Set system attributes for a file. The system attributes can either be
    passed as a list of verbose attribute names or a string that consists of
    a sequence of compact attribute options.

    Raises ValueError for invalid system attributes or OSError (with errno set)
    if any of the library calls fail.

    Input examples:
      verbose attributes example: ['hidden', 'archive', 'sensitive', ... ]

    compact attributes example: 'HAT'
    """

    from pkg.misc import force_bytes
    if not isinstance(filename, six.string_types):
        raise TypeError("filename must be string type")
    if not attr:
        raise TypeError("{0} is not a valid system attribute".format(attr))

    compact = False
    sys_attr = -1
    request = ffi.new("nvlist_t **")
    request[0] = ffi.gc(request[0], lib.nvlist_free)

    if lib.nvlist_alloc(request, lib.NV_UNIQUE_NAME, 0) != 0:
        raise OSError(ffi.errno, os.strerror(ffi.errno))

    # A single string indicates system attributes are passed in compact
    # form (e.g. AHi), verbose attributes are read as a list of strings.
    if isinstance(attr, six.string_types):
        compact = True

    for c in attr:
        c = force_bytes(c)
        if compact:
            sys_attr = lib.option_to_attr(c)
        else:
            sys_attr = lib.name_to_attr(c)

        if sys_attr == lib.F_ATTR_INVAL:
            if compact:
                raise ValueError("{0} is not a valid compact system "
                                 "attribute".format(attr))
            else:
                raise ValueError("{0} is not a valid verbose system "
                                 "attribute".format(attr))
        if not is_supported(sys_attr):
            if compact:
                raise ValueError("{0} is not a supported compact system "
                                 "attribute".format(attr))
            else:
                raise ValueError("{0} is not a supported verbose system "
                                 "attribute".format(attr))
        if lib.nvlist_add_boolean_value(request[0], lib.attr_to_name(sys_attr),
                                        1) != 0:
            raise OSError(ffi.errno, os.strerror(ffi.errno))

    fd = os.open(filename, os.O_RDONLY)
    if fd == -1:
        raise OSError(ffi.errno, os.strerror(ffi.errno), filename)

    if lib.fsetattr(fd, lib.XATTR_VIEW_READWRITE, request[0]):
        os.close(fd)
        raise OSError(ffi.errno, os.strerror(ffi.errno), filename)
    os.close(fd)