Beispiel #1
0
 def from_cffi(cls: t.Type[T], struct) -> T:
     return cls(
         nodeid=struct.nodeid,
         generation=struct.generation,
         entry_valid=Timespec(struct.entry_valid, struct.entry_valid_nsec),
         attr_valid=Timespec(struct.attr_valid, struct.attr_valid_nsec),
         attr=FuseAttr.from_cffi(struct.attr),
     )
Beispiel #2
0
 def from_cffi(cls: t.Type[T], struct) -> T:
     return cls(
         ino=struct.ino,
         size=struct.size,
         blocks=struct.blocks,
         atime=Timespec(sec=struct.atime, nsec=struct.atimensec),
         mtime=Timespec(sec=struct.mtime, nsec=struct.mtimensec),
         ctime=Timespec(sec=struct.ctime, nsec=struct.ctimensec),
         mode=struct.mode,
         nlink=struct.nlink,
         uid=struct.uid,
         gid=struct.gid,
         rdev=struct.rdev,
         blksize=struct.blksize,
     )
Beispiel #3
0
 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),
     )
Beispiel #4
0
 def test_stat(self) -> None:
     initial = Stat(
         dev=0,
         ino=0,
         mode=TypeMode(S_IF.REG, Mode(0o777)),
         nlink=0,
         uid=0,
         gid=0,
         rdev=0,
         size=0,
         blksize=0,
         blocks=0,
         atime=Timespec(sec=0, nsec=0),
         mtime=Timespec(sec=0, nsec=0),
         ctime=Timespec(sec=0, nsec=0),
     )
     output = Stat.from_bytes(initial.to_bytes())
     self.assertEqual(initial, output)
Beispiel #5
0
    async def test_symlink(self) -> None:
        @self.nursery.start_soon
        async def open() -> None:
            async with (await self.child.task.open(
                    await self.process.ptr(self.path / "foo"),
                    O.RDONLY)) as foo:
                data, _ = await foo.read(await
                                         self.process.malloc(bytes, 4096))

        await self.fuse.write((await self.assertRead(FuseGetattrOp)).respond(
            FuseAttrOut(attr_valid=Timespec(10000, 0),
                        attr=FuseAttr(ino=1,
                                      size=0,
                                      blocks=1,
                                      atime=Timespec(0, 0),
                                      mtime=Timespec(0, 0),
                                      ctime=Timespec(0, 0),
                                      mode=TypeMode(S_IF.DIR, Mode(0o777)),
                                      nlink=1,
                                      uid=self.fuse.uid,
                                      gid=self.fuse.gid,
                                      rdev=0,
                                      blksize=4096))))
        await self.fuse.write((await self.assertRead(FuseLookupOp)).respond(
            FuseEntryOut(
                nodeid=2,
                generation=1,
                entry_valid=Timespec(10000, 0),
                attr_valid=Timespec(10000, 0),
                # the size needs to be consistent with the data we'll actually send back on read
                # the kernel, I guess, handles delivering an eof;
                # we can just claim a larger size then send back less data
                attr=FuseAttr(ino=999,
                              size=4096,
                              blocks=1,
                              atime=Timespec(0, 0),
                              mtime=Timespec(0, 0),
                              ctime=Timespec(0, 0),
                              mode=TypeMode(S_IF.LNK, Mode(0o777)),
                              nlink=1,
                              uid=self.fuse.uid,
                              gid=self.fuse.gid,
                              rdev=0,
                              blksize=4096))))
        await self.fuse.write(
            (await self.assertRead(FuseReadlinkOp)).respond("/bin/sh"))
Beispiel #6
0
    async def test_basic(self) -> None:
        data_read_from_fuse = b"this is some data read from fuse"

        @self.nursery.start_soon
        async def open() -> None:
            foo = await self.child.task.open(
                await self.child.ptr(self.path / "foo"), O.RDONLY)
            data, _ = await foo.read(await self.child.malloc(bytes, 4096))
            self.assertEqual(data_read_from_fuse, await data.read())
            data, _ = await foo.read(await self.child.malloc(bytes, 4096))
            self.assertEqual(data.size(), 0)
            await foo.close()

            root = await self.child.task.open(await self.child.ptr(self.path),
                                              O.RDONLY)
            valid, rest = await root.getdents(await self.child.ram.malloc(
                DirentList, 4096))
            await root.close()

        root_getattr = await self.assertRead(FuseGetattrOp)
        if root_getattr.hdr.nodeid != 1:
            raise Exception("expected to get getattr for root node 1,  not",
                            root_getattr.hdr.nodeid)
        await self.fuse.write(
            root_getattr.respond(
                FuseAttrOut(attr_valid=Timespec(10000, 0),
                            attr=FuseAttr(ino=1,
                                          size=0,
                                          blocks=1,
                                          atime=Timespec(0, 0),
                                          mtime=Timespec(0, 0),
                                          ctime=Timespec(0, 0),
                                          mode=TypeMode(S_IF.DIR, Mode(0o777)),
                                          nlink=1,
                                          uid=self.fuse.uid,
                                          gid=self.fuse.gid,
                                          rdev=0,
                                          blksize=4096))))
        await self.fuse.write((await self.assertRead(FuseLookupOp)).respond(
            FuseEntryOut(
                nodeid=2,
                generation=1,
                entry_valid=Timespec(10000, 0),
                attr_valid=Timespec(10000, 0),
                # the size needs to be consistent with the data we'll actually send back on read
                # the kernel, I guess, handles delivering an eof
                attr=FuseAttr(ino=999,
                              size=len(data_read_from_fuse),
                              blocks=1,
                              atime=Timespec(0, 0),
                              mtime=Timespec(0, 0),
                              ctime=Timespec(0, 0),
                              mode=TypeMode(S_IF.REG, Mode(0o777)),
                              nlink=1,
                              uid=self.fuse.uid,
                              gid=self.fuse.gid,
                              rdev=0,
                              blksize=4096))))
        fh = 42
        await self.fuse.write((await self.assertRead(FuseOpenOp)).respond(
            FuseOpenOut(fh=fh, open_flags=FOPEN.NONE)))
        await self.fuse.write(
            (await self.assertRead(FuseReadOp)).respond(data_read_from_fuse))
        # close file
        await self.fuse.write((await self.assertRead(FuseFlushOp)).respond())
        await self.fuse.write((await self.assertRead(FuseReleaseOp)).respond())
        # open root and getdents
        root_fh = 137
        await self.fuse.write((await self.assertRead(FuseOpendirOp)).respond(
            FuseOpenOut(fh=root_fh, open_flags=FOPEN.NONE)))
        foobar_ino = 432
        await self.fuse.write((
            await self.assertRead(FuseReaddirplusOp)
        ).respond([
            FuseDirentplus(
                FuseEntryOut(
                    nodeid=foobar_ino,
                    generation=1,
                    entry_valid=Timespec(10000, 0),
                    attr_valid=Timespec(10000, 0),
                    # the size needs to be consistent with the data we'll actually send back on read
                    # the kernel, I guess, handles delivering an eof
                    attr=FuseAttr(ino=foobar_ino,
                                  size=len(data_read_from_fuse),
                                  blocks=1,
                                  atime=Timespec(0, 0),
                                  mtime=Timespec(0, 0),
                                  ctime=Timespec(0, 0),
                                  mode=TypeMode(S_IF.REG, Mode(0o777)),
                                  nlink=1,
                                  uid=self.fuse.uid,
                                  gid=self.fuse.gid,
                                  rdev=0,
                                  blksize=4096)),
                FuseDirent(
                    ino=foobar_ino,
                    off=1,
                    type=DT.REG,
                    name="foobar",
                ),
            ),
        ]))
        # close file
        await self.fuse.write((await
                               self.assertRead(FuseReleasedirOp)).respond())
Beispiel #7
0
 async def open() -> None:
     "Every filename in this filesystem is a symlink to stub_path"
     while True:
         try:
             [op] = await fuse.read()
         except OSError as e:
             # sure wish Python had a builtin ENODEV exception, that would come in handy
             if e.errno == errno.ENODEV:
                 # the filesystem has been unmounted, just return cleanly
                 return
             else:
                 raise
         sym_ino = 2
         fh = 42
         if isinstance(op, FuseGetattrOp):
             await fuse.write(
                 op.respond(
                     FuseAttrOut(attr_valid=Timespec(10000, 0),
                                 attr=FuseAttr(
                                     ino=1,
                                     size=0,
                                     blocks=1,
                                     atime=Timespec(0, 0),
                                     mtime=Timespec(0, 0),
                                     ctime=Timespec(0, 0),
                                     mode=TypeMode(
                                         S_IF.DIR, Mode(0o777)),
                                     nlink=1,
                                     uid=fuse.uid,
                                     gid=fuse.gid,
                                     rdev=0,
                                     blksize=4096))))
         elif isinstance(op, FuseLookupOp):
             await fuse.write(
                 op.respond(
                     FuseEntryOut(
                         nodeid=sym_ino,
                         generation=1,
                         entry_valid=Timespec(10000, 0),
                         attr_valid=Timespec(10000, 0),
                         # the size needs to be consistent with the data we'll actually send back on read
                         # the kernel, I guess, handles delivering an eof
                         attr=FuseAttr(ino=999,
                                       size=16,
                                       blocks=1,
                                       atime=Timespec(0, 0),
                                       mtime=Timespec(0, 0),
                                       ctime=Timespec(0, 0),
                                       mode=TypeMode(
                                           S_IF.LNK,
                                           Mode(0o777)),
                                       nlink=1,
                                       uid=fuse.uid,
                                       gid=fuse.gid,
                                       rdev=0,
                                       blksize=4096))))
         elif isinstance(op, FuseOpenOp):
             await fuse.write(
                 op.respond(
                     FuseOpenOut(fh=fh, open_flags=FOPEN.NONE)))
         elif isinstance(op, FuseGetxattrOp):
             await fuse.write(op.error(-errno.ENODATA))
         elif isinstance(op, FuseReadOp):
             await fuse.write(op.respond(bytes(16)))
         elif isinstance(op, FuseReleaseOp):
             await fuse.write(op.respond())
         elif isinstance(op, FuseReadlinkOp):
             await fuse.write(op.respond(stub_path))
         else:
             print("unhandled op", op)
             raise Exception("unhandled op", op)
Beispiel #8
0
 def from_header(cls: t.Type[T], data: bytes) -> T:
     struct = ffi.cast('struct fuse_attr_out*', ffi.from_buffer(data))
     return cls(
         attr_valid=Timespec(struct.attr_valid, struct.attr_valid_nsec),
         attr=FuseAttr.from_cffi(struct.attr),
     )