Skip to content

Instantly share code, notes, and snippets.

@ag4ve
Created April 22, 2014 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ag4ve/11171201 to your computer and use it in GitHub Desktop.
Save ag4ve/11171201 to your computer and use it in GitHub Desktop.
import os
import subprocess
import pprint
pp = pprint.PrettyPrinter(indent = 4)
class FileAttrList:
"""
Create a list of files and directories and their attributes and libraries
The file list should be an array of an arrays with:
[[node, username, groupname, mode], ...]
import FileAttrList
fal = FileAttrList(list)
fmt.AddUserMap(dict)
fmt.AddGroupMap(dict)
filelist = fal.GetList()
"""
def __init__(self, list):
self.inlist = list
self.usermap = []
self.groupmap = []
self.outlist = []
def Build(self):
"""
Compile the list of files and directories recursively (this shouldn't need
be run manually).
"""
self.outlist.extend(self.CheckProps(self.inlist))
self.outlist.extend(self.RecurseTree([i[0] for i in self.inlist]))
self.inlist = []
def GetList(self):
"""
Build and return the compiled list
"""
self.Build()
return self.outlist
def AddFiles(self, list):
self.inlist.append(list)
def CheckProps(self, filelist):
"""
Assure that user,group,mode is assigned to files and directories passed in.
files = fal.CheckProps([files])
"""
outlist = []
for attrs in filelist:
actual = [None]*4
if type(attrs[0]) == str and len(attrs[0]) > 0:
actual[0] = attrs[0]
else:
continue
mode = [None]*4
if os.path.exists(attrs[0]):
mode = self.__AddNode(attrs[0])
# UID
# If a uid is given in the config
if len(attrs) > 1 and type(attrs[1]) == int:
actual[1] = attrs[1]
# Convert a username to an id
elif len(attrs) > 1 and type(attrs[1]) == str and len(attrs[1]) > 0:
actual[1] = self.__GetUID(attrs[1])
# If no uid is not given but the file exists
elif len(mode) > 1:
actual[1] = mode[1]
else:
continue
# GID
# If a gid is given in the config
if len(attrs) > 2 and type(attrs[2]) == int:
actual[2] = attrs[2]
# Convert a group name to an id
elif len(attrs) > 2 and type(attrs[2]) == str and len(attrs[2]) > 0:
actual[2] = self.__GetGID(attrs[2])
# If no gid is not given but the file exists
elif len(mode) > 2:
actual[2] = mode[2]
else:
continue
# MOD
# If a mode is given in the config
if len(attrs) > 3 and int(str(attrs[3]), 8):
actual[3] = attrs[3]
# If no mode is not given but the file exists
elif len(mode) > 3 and len(mode[3]) > 0:
actual[3] = mode[3]
else:
continue
outlist.append(actual)
return outlist
def RecurseTree(self, filelist):
"""
Recurse a list of files and directories going down directories, symlinks,
libraries programs are linked against and return a list of (files, libs)
list = fal.RecurseTree([list])
"""
outlist = []
for filename in filelist:
if not os.path.exists(filename):
print("HERE1 [%s]" % filename)
continue
if os.path.isfile(filename):
print("HERE2 [%s]" % filename)
outlist.append(self.RecurseTree(self.__Ldd([filename])))
continue
for root, dirs, files in os.walk(filename):
print("HERE2")
# loop over directories and files in the path
for dir, file in map(lambda *x: x, dirs, files):
for node in [dir, file]:
if node is None: continue
# create a full path
filepath = root + '/' + node
if os.path.isfile(filepath):
outlist.append(self.RecurseTree(self.__Ldd([filepath])))
if os.path.islink(filepath):
# per help: symlinks to directories are not treated as directories
# so it is easiest just to recurse them and see what we find
outlist.append(self.RecurseTree([os.path.realpath(filepath)]))
if not self.__InList(filepath) and not name in list:
outlist.append(self.__AddNode(filepath))
return outlist
#
def __AddNode(self, filepath):
uid = self.__GetUser(filepath)
gid = self.__GetGroup(filepath)
mode = str(oct(os.stat(filepath).st_mode - 32768))[2:]
return [filepath, uid, gid, mode]
def __InList(self, name):
for node in self.outlist:
if node[0] == name:
return node
def AddUserMap(self, mapping):
"""
Add a map for [{username: uid}, ...]
fal.AddUserMap(dict)
"""
if type(mapping) != dict:
raise Exception("Must be a dictionary")
self.usermap = mapping
def AddGroupMap(self, mapping):
"""
Add a map for [{groupname: gid}, ...]
fal.AddGroupMap(dict)
"""
if type(mapping) != dict:
raise Exception("Must be a dictionary")
self.groupmap = mapping
def __GetUID(self, name):
print("in getuid [%s]" %(name))
return self.usermap[str(name)]
def __GetGID(self, name):
return self.groupmap[str(name)]
# Return the UID for a file
def __GetUser(self, filepath):
return os.stat(filepath).st_uid
# Return the GID for a file
def __GetGroup(self, filepath):
return os.stat(filepath).st_gid
# Return a list of libraries that are linked to a program
def __Ldd(self, filename):
libs = []
for x in filename:
p = subprocess.Popen(["ldd", x],
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for line in p.stdout:
s = line.split()
if "=>" in s:
if len(s) == 3: # virtual library
continue
else:
libs.append(s[2])
else:
if len(s) == 2:
libs.append(s[0])
pp.pprint(["ldd", libs])
return libs
#!/usr/bin/env python
from textwrap import dedent
from FileAttrList import FileAttrList
import pprint
pp = pprint.PrettyPrinter(indent = 4)
def main():
fattr = [
['/testroot', 0, 0, 777],
['/bin/dash']
]
pp.pprint(["fattr", fattr])
fal = FileAttrList(fattr)
filelist = fal.GetList()
pp.pprint(["filelist", filelist])
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment