diff options
Diffstat (limited to 'portage_with_autodep/pym/_emerge/EventsLogger.py')
-rw-r--r-- | portage_with_autodep/pym/_emerge/EventsLogger.py | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/portage_with_autodep/pym/_emerge/EventsLogger.py b/portage_with_autodep/pym/_emerge/EventsLogger.py new file mode 100644 index 0000000..68b3c67 --- /dev/null +++ b/portage_with_autodep/pym/_emerge/EventsLogger.py @@ -0,0 +1,180 @@ +# Distributed under the terms of the GNU General Public License v2 + +import io +import sys +import stat +import socket +import select +import tempfile + +import threading + +from portage import os + +class EventsLogger(threading.Thread): + def default_filter(eventname, filename, stage): + return True + + def __init__(self, socket_dir="/tmp/", filter_proc=default_filter): + threading.Thread.__init__(self) # init the Thread + + self.alive=False + + self.main_thread=threading.currentThread() + + self.socket_dir=socket_dir + self.filter_proc=filter_proc + + self.socket_name=None + self.socket_logger=None + + self.events={} + + try: + socket_dir_name = tempfile.mkdtemp(dir=self.socket_dir, + prefix="log_socket_") + + socket_name = os.path.join(socket_dir_name, 'socket') + + except OSError as e: + return + + self.socket_name=socket_name + + #print(self.socket_name) + + try: + socket_logger=socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) + socket_logger.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + socket_logger.bind(self.socket_name) + socket_logger.listen(64) + + except socket.error as e: + return + + self.socket_logger=socket_logger + + try: + # Allow connecting to socket for anyone + os.chmod(socket_dir_name, + stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR| + stat.S_IROTH|stat.S_IWOTH|stat.S_IXOTH) + os.chmod(socket_name, + stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR| + stat.S_IROTH|stat.S_IWOTH|stat.S_IXOTH) + except OSError as e: + return + + def run(self): + """ Starts the log server """ + + self.alive=True + self.listen_thread=threading.currentThread() + clients={} + + epoll=select.epoll() + epoll.register(self.socket_logger.fileno(), select.EPOLLIN) + + while self.alive: + try: + sock_events = epoll.poll(3) + + for fileno, sock_event in sock_events: + if fileno == self.socket_logger.fileno(): + ret = self.socket_logger.accept() + if ret is None: + pass + else: + (client,addr)=ret + epoll.register(client.fileno(), select.EPOLLIN) + clients[client.fileno()]=client + elif sock_event & select.EPOLLIN: + s=clients[fileno] + record=s.recv(8192) + + if not record: # if connection was closed + epoll.unregister(fileno) + clients[fileno].close() + del clients[fileno] + continue + + #import pdb; pdb.set_trace() + try: + message=record.decode("utf8").split("\0") + except UnicodeDecodeError: + print("Bad message %s" % record) + continue + + # continue + + #print(message) + + try: + if message[4]=="ASKING": + if self.filter_proc(message[1],message[2],message[3]): + s.sendall(b"ALLOW\0") + else: + # TODO: log through portage infrastructure + #print("Blocking an access to %s" % message[2]) + s.sendall(b"DENY\0") + else: + eventname,filename,stage,result=message[1:5] + + if not stage in self.events: + self.events[stage]=[{},{}] + + hashofsucesses=self.events[stage][0] + hashoffailures=self.events[stage][1] + + if result=="DENIED": + print("Blocking an access to %s" % filename) + + if result=="OK": + if not filename in hashofsucesses: + hashofsucesses[filename]=[False,False] + + readed_or_writed=hashofsucesses[filename] + + if eventname=="read": + readed_or_writed[0]=True + elif eventname=="write": + readed_or_writed[1]=True + + elif result[0:3]=="ERR" or result=="DENIED": + if not filename in hashoffailures: + hashoffailures[filename]=[False,False] + notfound_or_blocked=hashoffailures[filename] + + if result=="ERR/2": + notfound_or_blocked[0]=True + elif result=="DENIED": + notfound_or_blocked[1]=True + + else: + print("Error in logger module<->analyser protocol") + + except IndexError: + print("IndexError while parsing %s" % record) + except IOError as e: + if e.errno!=4: # handling "Interrupted system call" errors + raise + + # if main thread doesnt exists then exit + if not self.main_thread.is_alive(): + break + epoll.unregister(self.socket_logger.fileno()) + epoll.close() + self.socket_logger.close() + + def stop(self): + """ Stops the log server. Returns all events """ + + self.alive=False + + # Block the main thread until listener exists + self.listen_thread.join() + + # We assume portage clears tmp folder, so no deleting a socket file + # We assume that no new socket data will arrive after this moment + return self.events |