Пример #1
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)
Пример #2
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
     )
Пример #3
0
class InotifyEvent:
    wd: WatchDescriptor
    mask: IN
    cookie: int
    name: t.Optional[str]
    MINIMUM_SIZE_TO_READ_ONE_EVENT = ffi.sizeof('struct inotify_event') + NAME_MAX + 1

    def to_bytes(self) -> bytes:
        if self.name is not None:
            name = self.name.encode()
            name_len = len(name)
        else:
            name = b""
            name_len = 0
        return bytes(ffi.buffer(ffi.new('struct inotify_event*', {
            "wd": self.wd,
            "mask": self.mask,
            "cookie": self.cookie,
            "len": name_len,
            "name": name,
        })))

    T = t.TypeVar('T', bound='InotifyEvent')
    @classmethod
    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
Пример #4
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]))
Пример #5
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)
Пример #6
0
 def to_bytes(self) -> bytes:
     namebytes = self.name.encode() + b'\0'
     length = ffi.sizeof('struct fuse_dirent') + len(namebytes)
     padding = align(length, 8) - length
     namebytes = namebytes + bytes(padding)
     return bytes(
         ffi.buffer(
             ffi.new('struct fuse_dirent*',
                     self._to_cffi_dict(namebytes)))) + namebytes
Пример #7
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])
Пример #8
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
Пример #9
0
 def to_bytes(self) -> bytes:
     msg_data = self.msg_to_bytes()
     return bytes(
         ffi.buffer(
             ffi.new(
                 'struct fuse_out_header*', {
                     'len':
                     ffi.sizeof('struct fuse_out_header') + len(msg_data),
                     'error': self.hdr.error,
                     'unique': self.hdr.unique,
                 }))) + msg_data
Пример #10
0
 def to_bytes(self, val: T_cmsg) -> bytes:
     if not isinstance(val, self.cls):
         raise Exception("Serializer for", self.cls,
                         "had to_bytes called on different type", val)
     data = val.to_data()
     header = bytes(ffi.buffer(ffi.new('struct cmsghdr*', {
         "cmsg_len": ffi.sizeof('struct cmsghdr') + len(data),
         "cmsg_level": val.level(),
         "cmsg_type": val.type(),
     })))
     return header + data
Пример #11
0
 def to_bytes(self) -> bytes:
     namebytes = self.dirent.name.encode() + b'\0'
     length = ffi.sizeof('struct fuse_direntplus') + len(namebytes)
     padding = align(length, 8) - length
     namebytes = namebytes + bytes(padding)
     return bytes(
         ffi.buffer(
             ffi.new(
                 'struct fuse_direntplus*', {
                     "entry_out": self.entry_out._to_cffi_dict(),
                     "dirent": self.dirent._to_cffi_dict(namebytes),
                 }))) + namebytes
Пример #12
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]
Пример #13
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)
Пример #14
0
def split_iovec(iov: WrittenPointer[IovecList], ret: int
) -> t.Tuple[WrittenPointer[IovecList], t.Optional[t.Tuple[Pointer, Pointer]], WrittenPointer[IovecList]]:
    first, middle, last = iov.value.split_with_middle(ret)
    if middle is None:
        first_count = len(first)
    else:
        # we include the partially-consumed middle pointer in the first WP[IovecList] returned;
        # I think this is the most ergonomic choice, since in the normal case, I'll want to
        # operate on middle separately, then on second.
        first_count = len(first) + 1
    # TODO this is fairly ad-hoc, splitting on a WrittenPointer should really call into the
    # Serializer to determine validity. (And then I suppose we would have .degrade to degrade a
    # WrittenPointer back into a Pointer so we can split it??? Hmm, seems awkward...)
    first_ptr, last_ptr = iov.split(first_count * ffi.sizeof('struct iovec'))
    return first_ptr._wrote(first), middle, last_ptr._wrote(last)
Пример #15
0
 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)))
Пример #16
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct ifreq')
Пример #17
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct timespec')
Пример #18
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct signalfd_siginfo')
Пример #19
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct kernel_sigset')
Пример #20
0
 def to_bytes(self) -> bytes:
     addr = ffi.new('struct sockaddr_un*', (AF.UNIX, self.path))
     real_length = ffi.sizeof('sa_family_t') + len(self.path) + 1
     return bytes(ffi.buffer(addr))[:real_length]
Пример #21
0
            events = await self.wait()
            for event in events:
                if event.mask & mask and (event.name == name
                                          if name else True):
                    return event

    async def remove(self) -> None:
        "Remove this watch from inotify"
        await self.inotify.asyncfd.handle.inotify_rm_watch(self.wd)
        # we'll mark this Watch as removed once we get the IN_IGNORED event;
        # only after that do we know for sure that there are no more events
        # coming for this Watch.


_inotify_read_size = 4096
_inotify_minimum_size_to_read_one_event = (ffi.sizeof('struct inotify_event') +
                                           NAME_MAX + 1)
assert _inotify_read_size > _inotify_minimum_size_to_read_one_event


class Inotify:
    "An inotify file descriptor, which allows monitoring filesystem paths for events."

    def __init__(self, asyncfd: AsyncFileDescriptor, ram: RAM) -> None:
        "Private; use Inotify.make instead."
        self.asyncfd = asyncfd
        self.ram = ram
        self.wd_to_watch: t.Dict[WatchDescriptor, Watch] = {}
        self.running_wait = OneAtATime()

    @staticmethod
Пример #22
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct file_clone_range')
Пример #23
0
 def sizeof(cls) -> int:
     # this is the maximum size of a sockaddr
     return ffi.sizeof('struct sockaddr_storage')
Пример #24
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct kernel_sigaction')
Пример #25
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct sockaddr_storage')
Пример #26
0
 def sizeof(cls) -> int:
     return ffi.sizeof('cpu_set_t')
Пример #27
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct fdpair')
Пример #28
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct epoll_event')
Пример #29
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct sockaddr_un')
Пример #30
0
 def sizeof(cls) -> int:
     return ffi.sizeof('struct rlimit')