mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 12:59:02 +02:00

Adds Python wrappers around the xattr API from libc and the ACL API from libacl. (Bitbake rev: 538011256964d0253f8e3ab7ff1d6fd62c7c2f89) Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
127 lines
2.7 KiB
Python
Executable File
127 lines
2.7 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
#
|
|
# Copyright 2023 by Garmin Ltd. or its subsidiaries
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import sys
|
|
import ctypes
|
|
import os
|
|
import errno
|
|
|
|
libc = ctypes.CDLL("libc.so.6", use_errno=True)
|
|
fsencoding = sys.getfilesystemencoding()
|
|
|
|
|
|
libc.listxattr.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_size_t]
|
|
libc.llistxattr.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_size_t]
|
|
|
|
|
|
def listxattr(path, follow=True):
|
|
func = libc.listxattr if follow else libc.llistxattr
|
|
|
|
os_path = os.fsencode(path)
|
|
|
|
while True:
|
|
length = func(os_path, None, 0)
|
|
|
|
if length < 0:
|
|
err = ctypes.get_errno()
|
|
raise OSError(err, os.strerror(err), str(path))
|
|
|
|
if length == 0:
|
|
return []
|
|
|
|
arr = ctypes.create_string_buffer(length)
|
|
|
|
read_length = func(os_path, arr, length)
|
|
if read_length != length:
|
|
# Race!
|
|
continue
|
|
|
|
return [a.decode(fsencoding) for a in arr.raw.split(b"\x00") if a]
|
|
|
|
|
|
libc.getxattr.argtypes = [
|
|
ctypes.c_char_p,
|
|
ctypes.c_char_p,
|
|
ctypes.c_char_p,
|
|
ctypes.c_size_t,
|
|
]
|
|
libc.lgetxattr.argtypes = [
|
|
ctypes.c_char_p,
|
|
ctypes.c_char_p,
|
|
ctypes.c_char_p,
|
|
ctypes.c_size_t,
|
|
]
|
|
|
|
|
|
def getxattr(path, name, follow=True):
|
|
func = libc.getxattr if follow else libc.lgetxattr
|
|
|
|
os_path = os.fsencode(path)
|
|
os_name = os.fsencode(name)
|
|
|
|
while True:
|
|
length = func(os_path, os_name, None, 0)
|
|
|
|
if length < 0:
|
|
err = ctypes.get_errno()
|
|
if err == errno.ENODATA:
|
|
return None
|
|
raise OSError(err, os.strerror(err), str(path))
|
|
|
|
if length == 0:
|
|
return ""
|
|
|
|
arr = ctypes.create_string_buffer(length)
|
|
|
|
read_length = func(os_path, os_name, arr, length)
|
|
if read_length != length:
|
|
# Race!
|
|
continue
|
|
|
|
return arr.raw
|
|
|
|
|
|
def get_all_xattr(path, follow=True):
|
|
attrs = {}
|
|
|
|
names = listxattr(path, follow)
|
|
|
|
for name in names:
|
|
value = getxattr(path, name, follow)
|
|
if value is None:
|
|
# This can happen if a value is erased after listxattr is called,
|
|
# so ignore it
|
|
continue
|
|
attrs[name] = value
|
|
|
|
return attrs
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("path", help="File Path", type=Path)
|
|
|
|
args = parser.parse_args()
|
|
|
|
attrs = get_all_xattr(args.path)
|
|
|
|
for name, value in attrs.items():
|
|
try:
|
|
value = value.decode(fsencoding)
|
|
except UnicodeDecodeError:
|
|
pass
|
|
|
|
print(f"{name} = {value}")
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|