Пример #1
0
 def to_bytes(self) -> bytes:
     return bytes(ffi.buffer(ffi.new('struct msghdr*', {
         "msg_name": ffi.cast('void*', int(self.name.near)) if self.name else ffi.NULL,
         "msg_namelen": self.name.size() if self.name else 0,
         "msg_iov": ffi.cast('void*', int(self.iov.near)),
         "msg_iovlen": len(self.iov.value),
         "msg_control": ffi.cast('void*', int(self.control.near)) if self.control else ffi.NULL,
         "msg_controllen": self.control.size() if self.control else 0,
         "msg_flags": 0,
     })))
Пример #2
0
 def to_bytes(self) -> bytes:
     return bytes(
         ffi.buffer(
             ffi.new(
                 'struct kernel_sigaction const*', {
                     "ksa_handler":
                     ffi.cast('sighandler_t', int(self.handler)),
                     "ksa_flags":
                     self.flags,
                     "ksa_restorer":
                     ffi.cast('sigrestore_t', int(self.restorer or 0)),
                     "ksa_mask":
                     self.mask.to_cffi()[0],
                 })))
Пример #3
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     if len(data) < cls.sizeof():
         raise Exception("data too small", data)
     struct = ffi.cast('struct sockaddr_in6*', ffi.from_buffer(data))
     cls.check_family(AF(struct.sin6_family))
     return cls(socket.ntohs(struct.sin6_port), ipaddress.IPv6Address(bytes(struct.sin6_addr.s6_addr)),
                struct.sin6_flowinfo, struct.sin6_scope_id)
Пример #4
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     if len(data) < cls.sizeof():
         raise Exception("data too small", data)
     struct = ffi.cast('struct sockaddr_in*', ffi.from_buffer(data))
     cls.check_family(AF(struct.sin_family))
     return cls(socket.ntohs(struct.sin_port),
                socket.ntohl(struct.sin_addr.s_addr))
Пример #5
0
    def from_bytes(self, data: bytes) -> T_socketpair:
        struct = ffi.cast('struct fdpair const*', ffi.from_buffer(data))

        def make(n: int) -> FileDescriptor:
            return self.task.make_fd_handle(near.FileDescriptor(int(n)))

        return self.cls(make(struct.first), make(struct.second))
Пример #6
0
 def from_bytes(self, data: bytes) -> Sockbuf[T]:
     struct = ffi.cast('socklen_t*', ffi.from_buffer(data))
     socklen = struct[0]
     if socklen > self.buf.size():
         raise Exception("not enough buffer space to read socket, need", socklen)
     valid, rest = self.buf.split(socklen)
     return Sockbuf(valid, rest)
Пример #7
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct kernel_sigaction const*',
                       ffi.from_buffer(data))
     handler: t.Union[Sighandler, near.Address]
     int_handler = int(ffi.cast('long int', struct.ksa_handler))
     try:
         handler = Sighandler(int_handler)
     except ValueError:
         handler = near.Address(int_handler)
     int_restorer = int(ffi.cast('long int', struct.ksa_restorer))
     return cls(
         handler=handler,
         flags=SA(struct.ksa_flags),
         mask=Sigset.from_cffi(struct.ksa_mask),
         restorer=near.Address(int_restorer) if int_restorer else None,
     )
Пример #8
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T: # type: ignore
     family = ffi.cast('sa_family_t*', ffi.from_buffer(data))
     rest = data[ffi.sizeof('sa_family_t'):]
     return cls(
         family=AF(family[0]),
         data=rest
     )
Пример #9
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     # As with to_bytes, we can't just cast the bytes to a struct sockaddr_storage and read its data field,
     # because that would pad the data with a bunch of null bytes,
     # and would not preserve the length of the valid data
     family = ffi.cast('sa_family_t*', ffi.from_buffer(data))
     rest = data[ffi.sizeof('sa_family_t'):]
     return cls(family=AF(family[0]), data=rest)
Пример #10
0
 def to_bytes(self) -> bytes:
     ret = b""
     for ptr in self:
         ret += bytes(ffi.buffer(ffi.new('struct iovec const*', {
             "iov_base": ffi.cast('void*', int(ptr.near)),
             "iov_len": ptr.size(),
         })))
     return ret
Пример #11
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct siginfo const*', ffi.from_buffer(data))
     return cls(
         code=struct.si_code,
         pid=struct.si_pid,
         uid=struct.si_uid,
         status=struct.si_status,
     )
Пример #12
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('cpu_set_t*', ffi.from_buffer(data))
     ret: t.List[int] = []
     for i, val in enumerate(getattr(struct, '__bits')):
         inc = (64 * i)
         for bit in bits(val, one_indexed=False):
             ret.append(bit)
     return cls(ret)
Пример #13
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_getxattr_out*', ffi.from_buffer(data))
     variable = data[ffi.sizeof('struct fuse_getxattr_out'):]
     if len(variable) < struct.size:
         raise Exception("partial fuse_getxattr_out packet, received size",
                         len(variable), "expected size", struct.size)
     # -1 to strip null byte
     return cls(os.fsdecode(variable[:struct.size - 1]))
Пример #14
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_release_in*', ffi.from_buffer(data))
     return cls(
         fh=struct.fh,
         flags=O(struct.flags),
         release_flags=FUSE_RELEASE(struct.release_flags),
         lock_owner=struct.lock_owner,
     )
Пример #15
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_out_header*', ffi.from_buffer(data))
     if struct.len > len(data):
         raise Exception(
             "only part of the FUSE out packet was passed to from_bytes",
             "length field in header is", struct.len,
             "but passed buffer is only", len(data))
     msg_data = data[ffi.sizeof('struct fuse_out_header'):struct.len]
     return cls.from_header(FuseOutHeader.from_cffi(struct), msg_data)
Пример #16
0
 def to_handle(cffi_ptr) -> Pointer[NativeFunction]:
     pointer_int = int(ffi.cast('ssize_t', cffi_ptr))
     # TODO we're just making up a memory mapping that this pointer is inside;
     # we should figure out the actual mapping, and the size for that matter.
     mapping = MemoryMapping(task,
                             near.MemoryMapping(pointer_int, 0, 1),
                             far.File())
     return Pointer(mapping, NullGateway(), NativeFunctionSerializer(),
                    StaticAllocation())
Пример #17
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_read_in*', ffi.from_buffer(data))
     return cls(
         fh=struct.fh,
         offset=struct.offset,
         size=struct.size,
         read_flags=FUSE_READ(struct.read_flags),
         flags=O(struct.flags),
     )
Пример #18
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_init_in*', ffi.from_buffer(data))
     value = cls(
         major=struct.major,
         minor=struct.minor,
         max_readahead=struct.max_readahead,
         flags=FUSE_INIT(struct.flags),
     )
     return value
Пример #19
0
 def to_bytes(self) -> bytes:
     struct = ffi.new(
         'struct robust_list_head*', {
             'list':
             (ffi.cast('struct robust_list*', int(self.first.near)), ),
             'futex_offset': ffi.offsetof('struct futex_node', 'futex'),
             'list_op_pending': ffi.NULL,
         })
     return bytes(ffi.buffer(struct))
Пример #20
0
 async def batch_read(self, ops: t.List[Pointer]) -> t.List[bytes]:
     ret: t.List[bytes] = []
     for src in ops:
         if src.mapping.task.address_space != self.local_task.address_space:
             raise Exception("trying to read from pointer", src,
                             "not in local address space")
         buf = ffi.buffer(ffi.cast('void*', int(src.near)), src.size())
         ret.append(bytes(buf))
     return ret
Пример #21
0
 def from_bytes(self, data: bytes) -> T_cmsg:
     record = ffi.cast('struct cmsghdr*', ffi.from_buffer(data))
     if record.cmsg_level != self.cls.level():
         raise Exception("serializer for level", self.cls.level(),
                         "got message for level", record.cmsg_level)
     if record.cmsg_type != self.cls.type():
         raise Exception("serializer for type", self.cls.type(),
                         "got message for type", record.cmsg_type)
     return self.cls.from_data(self.task, data[ffi.sizeof('struct cmsghdr'):record.cmsg_len])
Пример #22
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct __user_cap_data_struct[2]', ffi.from_buffer(data))
     capset_names = ['effective', 'permitted', 'inheritable']
     capsets: t.List[t.Set[CAP]] = []
     for name in capset_names:
         one, two = getattr(struct[0], name), getattr(struct[1], name)
         capset = from_uint32s(one, two)
         capsets.append(capset)
     return cls(*capsets)
Пример #23
0
 def from_bytes(cls: t.Type[T], data: bytes) -> t.Tuple[T, int]:
     struct = ffi.cast('struct inotify_event*', ffi.from_buffer(data))
     value = cls(
         wd=WatchDescriptor(struct.wd),
         mask=IN(struct.mask),
         cookie=struct.cookie,
         name=ffi.string(struct.name, struct.len).decode() if struct.len else None,
     )
     size = ffi.sizeof("struct inotify_event") + struct.len
     return value, size
Пример #24
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     entries = []
     while len(data) > 0:
         record = ffi.cast('struct linux_dirent64*', ffi.from_buffer(data))
         name_len = record.d_reclen - _d_name_offset
         # the name is padded with null bytes to make the dirent aligned,
         # so we have to use strlen to find the end
         name = ffi.string(record.d_name, name_len).decode()
         entries.append(Dirent(inode=record.d_ino, offset=record.d_off, type=DT(record.d_type), name=name))
         data = data[record.d_reclen:]
     return cls(entries)
Пример #25
0
 async def read_cffi(self, name: str) -> t.Any:
     "Read, parse, and return this fixed-size cffi type."
     size = ffi.sizeof(name)
     data = await self.read_length(size)
     if data is None:
         raise EOFException("got EOF while expecting to read a", name)
     nameptr = name + '*'
     dest = ffi.new(nameptr)
     # ffi.cast drops the reference to the backing buffer, so we have to copy it
     src = ffi.cast(nameptr, ffi.from_buffer(data))
     ffi.memmove(dest, src, size)
     return dest[0]
Пример #26
0
 def from_bytes(self, data: bytes) -> T_cmsglist:
     entries = []
     while len(data) > 0:
         record = ffi.cast('struct cmsghdr*', ffi.from_buffer(data))
         record_data = data[:record.cmsg_len]
         level = SOL(record.cmsg_level)
         if level == SOL.SOCKET and record.cmsg_type == int(SCM.RIGHTS):
             entries.append(CmsgSCMRights.get_serializer(self.task).from_bytes(record_data))
         else:
             raise Exception("unknown cmsg level/type sorry", level, type)
         data = data[record.cmsg_len:]
     return self.cls(entries)
Пример #27
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_init_out*', ffi.from_buffer(data))
     return cls(
         major=struct.major,
         minor=struct.minor,
         max_readahead=struct.max_readahead,
         flags=FUSE_INIT(struct.flags),
         max_background=struct.max_background,
         congestion_threshold=struct.congestion_threshold,
         max_write=struct.max_write,
         time_gran=struct.time_gran,
     )
Пример #28
0
 def from_header(cls: t.Type[T], hdr: FuseOutHeader, data: bytes) -> T:
     entries = []
     while len(data) > 0:
         # We do the work of from_bytes in this class instead of in Dirent because we need the
         # raw length field from the struct; merely doing len(name) will exclude padding.
         struct = ffi.cast('struct fuse_dirent*', ffi.from_buffer(data))
         record_length = ffi.sizeof('struct fuse_dirent') + struct.namelen
         if len(data) < record_length:
             raise Exception(
                 "partial packet passed to FuseDirent.from_bytes")
         entries.append(FuseDirent.from_cffi(struct))
         data = data[record_length:]
     return cls(hdr=hdr, msg=entries)
Пример #29
0
 def from_bytes(cls: t.Type[T], data: bytes) -> T:
     entries = []
     while len(data) > 0:
         # We do the work of from_bytes in this class instead of in Dirent because we need the
         # raw length field from the struct; merely doing len(name) will exclude padding.
         record = ffi.cast('struct linux_dirent64*', ffi.from_buffer(data))
         name_len = record.d_reclen - _d_name_offset
         # the name is padded with null bytes to make the dirent aligned,
         # so we have to use strlen to find the end
         name = ffi.string(record.d_name, name_len).decode()
         entries.append(Dirent(inode=record.d_ino, offset=record.d_off, type=DT(record.d_type), name=name))
         data = data[record.d_reclen:]
     return cls(entries)
Пример #30
0
 def from_bytes(self, data: bytes) -> RecvMsghdrOut:
     struct = ffi.cast('struct msghdr*', ffi.from_buffer(data))
     if self.name is None:
         name: t.Optional[Pointer[Address]] = None
         name_rest: t.Optional[Pointer[Address]] = None
     else:
         name, name_rest = self.name.split(struct.msg_namelen)
     if self.control is None:
         control: t.Optional[Pointer[CmsgList]] = None
         control_rest: t.Optional[Pointer[CmsgList]] = None
     else:
         control, control_rest = self.control.split(struct.msg_controllen)
     flags = MsghdrFlags(struct.msg_flags)
     return RecvMsghdrOut(name, control, flags, name_rest, control_rest)