#!/usr/bin/env python3
# SPDX-License-Identifier: WTFPL
# filter a file list based on whether xattrs have desired values
# example:
#	filter-xattrs user.foo=bar -user.qux *
# searches all files having "user.foo" set to "bar" and not having "user.qux"

import os
import re
import shutil
import subprocess
import sys

try:
	from xattr import getxattr, listxattr
except ImportError:
	if not shutil.which("getfattr"):
		sys.exit("neither getfattr nor xattr commands are installed")

	def getxattr(filename, attrname):
		return subprocess.check_output([
			"getfattr",
			"--only-values",
			"-n", attrname.decode(),
			filename.decode(),
		])


	def listxattr(filename):
		res = subprocess.check_output([
			"getfattr",
			filename.decode(),
		], encoding="utf-8")
		return res.strip().splitlines()[1:]


def usage(msg=""):
	if msg:
		print(msg, file=sys.stderr)
		print(file=sys.stderr)

	print("usage: %s FILTERS... FILES..." % sys.argv[0], file=sys.stderr)
	print(file=sys.stderr)
	print("Filters are:", file=sys.stderr)
	print("XATTR=VALUE for searching XATTR set to VALUE", file=sys.stderr)
	print("-XATTR for searcing XATTR unset", file=sys.stderr)
	sys.exit(64)


unsets = []
sets = []

for n, arg in enumerate(sys.argv[1:], 1):
	if arg.startswith("-"):
		unsets.append(arg[1:])
	elif re.match(r"(?:security|system|trusted|user)\.", arg):
		k, _, v = arg.partition("=")
		sets.append((k, v))
	else:
		break
else:
	usage("error: no FILES given")

if not (unsets or sets):
	usage("error: no FILTERS given")

matches = []
for file in sys.argv[n:]:
	bad = False

	attrs = {attr for attr in listxattr(file.encode())}
	for unsetattr in unsets:
		if unsetattr in attrs:
			bad = True
			break
	if bad:
		continue

	for k, v in sets:
		if k not in attrs:
			bad = True
			break
		if getxattr(file.encode(), k.encode()).decode() != v:
			bad = True
			break
	if bad:
		continue

	matches.append(file)

for match in matches:
	print(match)
if not matches:
	sys.exit(1)
