Пример #1
0
 def save_to_block(self, block: int) -> None:
     """ Set the metadata space of the given block (from 0 to 38, inclusive) to this metadata. """
     full_block = FileTable().read_block(block)
     data_section = full_block[START_OF_CONTENT:]
     new_bytes = self.form_bytes() + data_section
     write_block(block, new_bytes)
     FMLog.success(f"Wrote new metadata to block {block}")
Пример #2
0
    def mkdir(self, path, mode):
        self.files[path] = dict(st_mode=(S_IFDIR | mode),
                                st_nlink=2,
                                st_size=0,
                                st_ctime=time(),
                                st_mtime=time(),
                                st_atime=time())
        name = path
        mode = self.files[path].get('st_mode')
        ctime = self.files[path].get('st_ctime')
        mtime = self.files[path].get('st_mtime')
        atime = self.files[path].get('st_atime')
        nlink = self.files[path].get('st_nlink')
        size = self.files[path].get('st_size')
        uid = os.getuid()
        gid = os.getgid()
        self.chown(path, uid, gid)
        # get free block for the new created file to save the metadata.
        num_array = Format.get_free_block(Format, 1)
        block_num = num_array[0]
        # set up the location in the disk
        inode_data = Format.set_inode(Format, name, mode, ctime, mtime, atime,
                                      nlink, uid, gid, size, block_num)
        disktools.write_block(block_num, inode_data)
        # update the free block bitmap
        Format.update_bit_map(Format, num_array)

        # find the parent path and add the nlink by 1.
        parent_path = Format.find_parent_path(Format, path)
        self.files[parent_path]['st_nlink'] += 1
        Format.update_nlink(Format, parent_path, 1)
Пример #3
0
    def create(self, path, mode):
        self.files[path] = dict(st_mode=(S_IFREG | mode),
                                st_nlink=1,
                                st_size=0,
                                st_ctime=time(),
                                st_mtime=time(),
                                st_atime=time())

        name = path
        mode = self.files[path].get('st_mode')
        ctime = self.files[path].get('st_ctime')
        mtime = self.files[path].get('st_mtime')
        atime = self.files[path].get('st_atime')
        nlink = self.files[path].get('st_nlink')
        size = self.files[path].get('st_size')
        uid = os.getuid()
        gid = os.getgid()
        self.chown(path, uid, gid)
        # get free block for the new created file to save the metadata.
        num_array = Format.get_free_block(Format, 1)
        block_num = num_array[0]
        # set up the location in the disk
        inode_data = Format.set_inode(Format, name, mode, ctime, mtime, atime,
                                      nlink, uid, gid, size, block_num)
        disktools.write_block(block_num, inode_data)
        # update the free block bitmap
        Format.update_bit_map(Format, num_array)

        self.fd += 1
        return self.fd
Пример #4
0
    def clear_data_block(self, path):
        for i in range(1, NUM_BLOCKS, 1):
            data_block = []
            num_array = []
            clean_block = bytearray([0] * BLOCK_SIZE)
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:

                block_number = disktools.bytes_to_int(
                    block[LOCATION_START:LOCATION_FINISH])
                block_number_bin = bin(block_number)

                for b in block_number_bin[2:]:
                    num_array.append(int(b))

                num_array = list(reversed(num_array))

                for idx, val in enumerate(num_array):
                    if val == 1:
                        data_block.append(idx)

                for data in data_block:

                    disktools.write_block(data, clean_block)

                self.update_bit_map(self, data_block)
Пример #5
0
    def write_bytes_to_block(
        self, data: bytearray, overwrite: List[int] = [], print: bool = False
    ) -> List[int]:
        # print(overwrite)
        # print(data)
        data_as_bytes = data
        size = len(data_as_bytes)

        split_blocks = [
            data_as_bytes[i * BLOCK_SIZE : (i + 1) * BLOCK_SIZE]
            for i in range((size + BLOCK_SIZE - 1) // BLOCK_SIZE)
        ]

        written_blocks: List[int] = []

        def get_block_to_write(level: int) -> int:
            if level < len(overwrite):
                return overwrite[level]
            return self.find_free_block(written_blocks)

        iterator = 0

        for i in split_blocks:
            free: int = get_block_to_write(iterator)
            write_block(free, i)
            written_blocks.append(free)
            iterator += 1

        return written_blocks
Пример #6
0
    def update_mode(self, path, mode):

        for i in range(1, NUM_BLOCKS, 1):
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
                block[MODE_START:MODE_FINISH] = disktools.int_to_bytes(mode, 2)
                disktools.write_block(i, block)

        return 0
Пример #7
0
    def update_name(self, path, new_path):

        for i in range(1, NUM_BLOCKS, 1):
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
                block[NAME_START:NAME_FINISH] = new_path.encode()
                disktools.write_block(i, block)

        return 0
Пример #8
0
    def update_file_location(self, path, bitmap):
        for i in range(1, NUM_BLOCKS, 1):
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
                block[LOCATION_START:LOCATION_FINISH] = disktools.int_to_bytes(
                    bitmap, 2)
                disktools.write_block(i, block)

        return 0
Пример #9
0
 def clear_metadata_block(self, path):
     for i in range(1, NUM_BLOCKS, 1):
         block = disktools.read_block(i)
         if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
             num_array = []
             clean_block = bytearray([0] * BLOCK_SIZE)
             disktools.write_block(i, clean_block)
             num_array.append(i)
             self.update_bit_map(self, num_array)
Пример #10
0
    def update_owner(self, path, uid, gid):

        for i in range(1, NUM_BLOCKS, 1):
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
                block[UID_START:UID_FINISH] = disktools.int_to_bytes(uid, 2)
                block[GID_START:GID_FINISH] = disktools.int_to_bytes(gid, 2)
                disktools.write_block(i, block)

        return 0
Пример #11
0
 def write_to_table(self, locations: List[int]) -> None:
     filetable = self.get_filetable()
     location_len = len(locations)
     for i in range(location_len):
         location = locations[i]
         if i + 1 == location_len:
             filetable[location] = END_OF_FILE
         else:
             filetable[location] = locations[i + 1]
     to_write = filetable
     write_block(0, to_write)
Пример #12
0
    def update_bit_map(self, used_block):
        block = disktools.read_block(0)
        # get the int number of bitmap
        bitmap = disktools.bytes_to_int(block[BITMAP_START:BITMAP_FINISH])

        for i in used_block:
            bitmap = bits.toggleBit(bitmap, i)

        block[BITMAP_START:BITMAP_FINISH] = disktools.int_to_bytes(bitmap, 2)
        disktools.write_block(0, block)
        return bitmap
Пример #13
0
    def update_nlink(self, path, update):

        for i in range(0, NUM_BLOCKS, 1):
            block = disktools.read_block(i)
            if block[NAME_START:NAME_FINISH].decode().rstrip('\x00') == path:
                new_nlink = disktools.bytes_to_int(
                    block[NLINK_START:NLINK_FINISH]) + update
                block[NLINK_START:NLINK_FINISH] = disktools.int_to_bytes(
                    new_nlink, 1)
                disktools.write_block(i, block)

        return 0
Пример #14
0
    def purge_full_file(self, at_location: int) -> None:
        current_block = at_location
        filetable_snapshot = self.get_filetable()

        next_block = filetable_snapshot[at_location]
        while True:
            filetable_snapshot[current_block] = FREE_SPACE
            write_block(current_block, bytearray([0] * BLOCK_SIZE))
            current_block = next_block
            if current_block == END_OF_FILE:
                break
            next_block = filetable_snapshot[current_block]
        write_block(0, filetable_snapshot)
Пример #15
0
 def initial_root_metadata(self):
     now = time()
     name = '/'
     mode = (S_IFDIR | 0o755)
     ctime = now,
     mtime = now,
     atime = now,
     nlink = 2
     uid = os.getuid()
     gid = os.getgid()
     size = 0
     block_num = 0
     inode_data = self.set_inode(self, name, mode, ctime[0], mtime[0],
                                 atime[0], nlink, uid, gid, size, block_num)
     disktools.write_block(0, inode_data)
Пример #16
0
    def write_to_block(self, data: str, metadata: bytearray) -> List[int]:
        data_as_bytes = metadata + bytearray(data.encode(encoding="ascii"))
        size = len(data_as_bytes)

        split_blocks = [
            data_as_bytes[i * BLOCK_SIZE : (i + 1) * BLOCK_SIZE]
            for i in range((size + BLOCK_SIZE - 1) // BLOCK_SIZE)
        ]

        written_blocks: List[int] = []

        for i in split_blocks:
            free: int = self.find_free_block(written_blocks)
            write_block(free, i)
            written_blocks.append(free)
        return written_blocks
Пример #17
0
    def write(self, path, data, offset, fh):
        self.data[path] = (
            # make sure the data gets inserted at the right offset
            self.data[path][:offset].ljust(offset, '\x00'.encode('ascii')) +
            data
            # and only overwrites the bytes that data is replacing
            + self.data[path][offset + len(data):])
        self.files[path]['st_size'] = len(self.data[path])

        # get the length of input data
        size = len(self.data[path])
        # calculate the number of blocks that need to store the data
        no_of_blocks = (size // BLOCK_SIZE) + 1
        # get the free blocks
        num_array = Format.get_free_block(Format, no_of_blocks)
        Format.clear_data_block(Format, path)
        # set the data block bitmap
        data_block_bitmap = Format.set_data_block_bitmap(Format, num_array)
        # get the input data
        input_data = self.data[path]

        # save the data to disk into the allocated blocks
        for i in range(no_of_blocks):
            if no_of_blocks == 1:
                disktools.write_block(num_array[i], input_data)
            else:
                disktools.write_block(num_array[i],
                                      input_data[i * 64:i * 64 + 64])
        # Add the data block bitmap into the metadata information
        Format.update_file_location(Format, path, data_block_bitmap)
        # update the st_size in the metadata
        Format.update_size(Format, path, self.files[path]['st_size'])
        # update the st_mtime in the metadata
        Format.update_mtime(Format, path, int(time()))
        # update the free block bitmap
        Format.update_bit_map(Format, num_array)

        return len(data)
Пример #18
0
    def initial_free_block_bitmap(self):
        # initialise the bitmap int value to 0
        bitmap = 0
        # counter for count the blocks
        count = 0
        for i in range(NUM_BLOCKS):
            # read each block in the disk
            block = disktools.read_block(i)

            # set the value to 0 for the non-free block in bit map
            if disktools.bytes_to_int(block) != 0:
                bitmap = bits.clearBit(bitmap, count)
                count += 1
            else:
                bitmap = bits.setBit(bitmap, count)
                count += 1

        # set the first block to 1 which means it is not free(will store bitmap into block 0).
        bitmap = bits.clearBit(bitmap, 0)
        # write the bitmap value at the first two bytes at block 0
        bitmap_disk = disktools.read_block(0)
        bitmap_disk[BITMAP_START:BITMAP_FINISH] = disktools.int_to_bytes(
            bitmap, 2)
        disktools.write_block(0, bitmap_disk)
Пример #19
0
# Filetable
initial_table_block = bytearray([FREE_SPACE] * NUM_BLOCKS)
initial_table_block[0] = END_OF_FILE
initial_table_block[1] = END_OF_FILE

FMLog.warn("✔  Created filetable in disk block 0")

now = time()
dir_meta = (MetadataFactory().set_with_params(
    LOCATION=0x01,
    MODE=(S_IFDIR | 0o755),
    ATIME=int(now),
    CTIME=int(now),
    MTIME=int(now),
    NLINKS=2,
    GID=os.getgid(),
    UID=os.getuid(),
    NAME="FMFS",
    TYPE=0,
    SIZE=64,
).construct().form_bytes())

root_dir = bytearray([0] * (BLOCK_SIZE - len(dir_meta)))
write_block(0, initial_table_block)
write_block(1, dir_meta + root_dir)

FMLog.warn("✔  Created root directory in disk block 1")

FMLog.trace(
    "🚀 Installation and initialization of the FM Filesystem is complete!")