119 lines
2.6 KiB
Python
119 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
#
|
|
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
|
|
#
|
|
|
|
import io
|
|
import os
|
|
|
|
from qiling.os.posix import stat
|
|
|
|
|
|
class SimpleStringBuffer(io.BytesIO):
|
|
"""Simple FIFO pipe.
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
# Compatible with old implementation
|
|
def seek(self, offset: int, origin: int = 0) -> int:
|
|
# Imitate os.lseek
|
|
raise OSError("Illega Seek")
|
|
|
|
def seekable(self) -> bool:
|
|
return False
|
|
|
|
def write(self, buf: bytes) -> int:
|
|
# For the FIFO stream, the write doesn't change pos.
|
|
pos = super().tell()
|
|
super().seek(0, os.SEEK_END)
|
|
ret = super().write(buf)
|
|
super().seek(pos)
|
|
return ret
|
|
|
|
# Compatible with previous TextIO
|
|
@property
|
|
def name(self):
|
|
return None
|
|
|
|
|
|
class SimpleStreamBase:
|
|
def __init__(self, fd: int):
|
|
super().__init__()
|
|
|
|
self.__fd = fd
|
|
self.__closed = False
|
|
|
|
def close(self) -> None:
|
|
self.__closed = True
|
|
|
|
@property
|
|
def closed(self) -> bool:
|
|
return self.__closed
|
|
|
|
def fileno(self) -> int:
|
|
return self.__fd
|
|
|
|
def fstat(self):
|
|
return stat.Fstat(self.fileno())
|
|
|
|
|
|
class SimpleInStream(SimpleStreamBase, SimpleStringBuffer):
|
|
"""Simple input stream. May be used to mock stdin.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
class SimpleOutStream(SimpleStreamBase, SimpleStringBuffer):
|
|
"""Simple output stream. May be used to mock stdout or stderr.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
class NullOutStream(SimpleStreamBase):
|
|
"""Null out-stream, may be used to disregard process output.
|
|
"""
|
|
|
|
def write(self, s: bytes) -> int:
|
|
return len(s)
|
|
|
|
def flush(self) -> None:
|
|
pass
|
|
|
|
def writable(self) -> bool:
|
|
return True
|
|
|
|
|
|
class SimpleBufferedStream(io.BytesIO):
|
|
"""Simple buffered IO.
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
|
|
class InteractiveInStream(io.BytesIO):
|
|
def read(self, size: int) -> bytes:
|
|
'''
|
|
Read from the BytesIO buffer. If theres no data left in the buffer, get additional user input
|
|
|
|
Args:
|
|
size (int): The amount of bytes to read from the buffer
|
|
Returns:
|
|
bytes: The data read from the buffer
|
|
'''
|
|
|
|
# get the amount of bytes left in the buffer
|
|
bytes_left = self.getbuffer().nbytes - self.tell()
|
|
|
|
# if theres no bytes left in the buffer, get user input
|
|
if bytes_left == 0:
|
|
user_data = input().encode() + b'\x0a'
|
|
self.write(user_data)
|
|
self.seek(-len(user_data), io.SEEK_CUR)
|
|
|
|
return super().read(size)
|