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)
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))
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)
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 )
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))
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)
def from_bytes(cls: t.Type[T], data: bytes) -> T: if len(data) != cls.sizeof(): raise Exception("data length", len(data), "doesn't match actual length of struct ifreq", cls.sizeof()) cffi = ffi.new('struct ifreq*') ffi.memmove(cffi, ffi.from_buffer(data), cls.sizeof()) return cls(cffi=cffi)
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)
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, )
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, )
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]))
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)
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
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)
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), )
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])
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
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)
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, )
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]
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)
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)
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)
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)
def from_bytes(cls: t.Type[T], data: bytes) -> T: struct = ffi.cast('struct fuse_in_header*', ffi.from_buffer(data)) if struct.len > len(data): raise Exception( "only part of the FUSE in packet was passed to from_bytes", "length field in header is", struct.len, "but passed buffer is only", len(data)) opcode = FUSE_OPCODE(struct.opcode) if opcode != cls.opcode: raise Exception("mismatch between opcode in header", opcode, "and opcode for this class", cls.opcode) hdr = FuseInHeader.from_cffi(struct) variable = data[FuseInHeader.sizeof():struct.len] msg = cls.from_header(hdr, variable) return msg
def fuse_in_parse_split(data: bytes) -> t.Tuple[FuseIn, bytes]: "Split the buffer into parsed header with variable length section, and remaining unparsed data" struct = ffi.cast('struct fuse_in_header*', ffi.from_buffer(data)) if struct.len > len(data): raise Exception( "only part of the FUSE packet was passed to _header_parse_split", "length field in header is", struct.len, "but passed buffer is only", len(data)) opcode = FUSE_OPCODE(struct.opcode) hdr = FuseInHeader.from_cffi(struct) variable = data[FuseInHeader.sizeof():struct.len] rest = data[struct.len:] # dispatch to the specific message type msg = opcode_classes[opcode].from_header(hdr, variable) return msg, rest
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, )
def from_bytes(self, data: bytes) -> RecvMsghdrOut: struct = ffi.cast('struct msghdr*', ffi.from_buffer(data)) if self.name is None: name: t.Optional[ReadablePointer[Sockaddr]] = None name_rest: t.Optional[Pointer[Sockaddr]] = None else: name, name_rest = self.name.readable_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.readable_split( struct.msg_controllen) flags = MsghdrFlags(struct.msg_flags) return RecvMsghdrOut(name, control._linearize() if control else None, flags, name_rest, control_rest)
def from_bytes(cls: t.Type[T], data: bytes) -> T: struct = ffi.cast('struct stat*', ffi.from_buffer(data)) return cls( dev=struct.st_dev, ino=struct.st_ino, mode=struct.st_mode, nlink=struct.st_nlink, uid=struct.st_uid, gid=struct.st_gid, rdev=struct.st_rdev, size=struct.st_size, blksize=struct.st_blksize, blocks=struct.st_blocks, atime=Timespec.from_cffi(struct.st_atim), mtime=Timespec.from_cffi(struct.st_mtim), ctime=Timespec.from_cffi(struct.st_ctim), )
def from_bytes(cls: t.Type[T], data: bytes) -> T: header = ffi.sizeof('sa_family_t') if len(data) < header: raise Exception("data too smalllll", data) struct = ffi.cast('struct sockaddr_un*', ffi.from_buffer(data)) cls.check_family(AF(struct.sun_family)) if len(data) == header: # unnamed socket, name is empty length = 0 elif struct.sun_path[0] == b'\0': # abstract socket, entire buffer is part of path length = len(data) - header else: # TODO handle the case where there's no null terminator # pathname socket, path is null-terminated length = lib.strlen(struct.sun_path) return cls(bytes(ffi.buffer(struct.sun_path, length)))