platform_system_sepolicy/tests/FcSort.py

126 lines
3.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python
import sys
import os
class FileContextsNode:
path = None
fileType = None
context = None
Type = None
meta = None
stemLen = None
strLen = None
Type = None
def __init__(self, path, fileType, context, meta, stemLen, strLen):
self.path = path
self.fileType = fileType
self.context = context
self.meta = meta
self.stemLen = stemLen
self.strlen = strLen
self.Type = context.split(":")[2]
metaChars = frozenset(['.', '^', '$', '?', '*', '+', '|', '[', '(', '{'])
escapedMetaChars = frozenset(['\.', '\^', '\$', '\?', '\*', '\+', '\|', '\[', '\(', '\{'])
def getStemLen(path):
global metaChars
stemLen = 0
i = 0
while i < len(path):
if path[i] == "\\":
i += 1
elif path[i] in metaChars:
break
stemLen += 1
i += 1
return stemLen
def getIsMeta(path):
global metaChars
global escapedMetaChars
metaCharsCount = 0
escapedMetaCharsCount = 0
for c in metaChars:
if c in path:
metaCharsCount += 1
for c in escapedMetaChars:
if c in path:
escapedMetaCharsCount += 1
return metaCharsCount > escapedMetaCharsCount
def CreateNode(line):
global metaChars
if (len(line) == 0) or (line[0] == '#'):
return None
split = line.split()
path = split[0].strip()
context = split[-1].strip()
fileType = None
if len(split) == 3:
fileType = split[1].strip()
meta = getIsMeta(path)
stemLen = getStemLen(path)
strLen = len(path.replace("\\", ""))
return FileContextsNode(path, fileType, context, meta, stemLen, strLen)
def ReadFileContexts(files):
fc = []
for f in files:
fd = open(f)
for line in fd:
node = CreateNode(line.strip())
if node != None:
fc.append(node)
return fc
# Comparator function for list.sort() based off of fc_sort.c
# Compares two FileContextNodes a and b and returns 1 if a is more
# specific or -1 if b is more specific.
def compare(a, b):
# The regex without metachars is more specific
if a.meta and not b.meta:
return -1
if b.meta and not a.meta:
return 1
# The regex with longer stemlen (regex before any meta characters) is more specific.
if a.stemLen < b.stemLen:
return -1
if b.stemLen < a.stemLen:
return 1
# The regex with longer string length is more specific
if a.strLen < b.strLen:
return -1
if b.strLen < a.strLen:
return 1
# A regex with a fileType defined (e.g. file, dir) is more specific.
if a.fileType is None and b.fileType is not None:
return -1
if b.fileType is None and a.fileType is not None:
return 1
# Regexes are equally specific.
return 0
def FcSort(files):
for f in files:
if not os.path.exists(f):
sys.exit("Error: File_contexts file " + f + " does not exist\n")
Fc = ReadFileContexts(files)
Fc.sort(cmp=compare)
return Fc
if __name__ == '__main__':
if len(sys.argv) < 2:
sys.exit("Usage: fc_sort.py <file_contexts 1> <file_contexts 2> <file_contexts 3>")
FcSorted = FcSort(sys.argv[1:])