Esempio n. 1
0
    def parse_dir_entries_in_address(
        self,
        address: int = 0,
        max_address: int = 0,
        tmp_lfn_entry: FATLongDirectoryEntry = FATLongDirectoryEntry()):
        """Parses directory entries in address range."""
        dir_hdr_size = FATDirectoryEntry.FAT_DIRECTORY_HEADER_SIZE

        if max_address == 0:
            max_address = FATDirectoryEntry.FAT_DIRECTORY_HEADER_SIZE

        dir_entries = []

        for hdr_addr in range(address, max_address, dir_hdr_size):
            # Parse each entry
            dir_hdr = self.__parse_dir_entry(hdr_addr)
            dir_sn = EightDotThree(encoding=self.encoding)
            try:
                dir_sn.set_byte_name(dir_hdr["DIR_Name"])
            except NotAFatEntryException as ex:
                # Not a directory of any kind, invalidate temporary LFN entries
                tmp_lfn_entry = FATLongDirectoryEntry()
                if ex.free_type == ex.FREE_ENTRY:
                    # Empty directory entry,
                    continue
                elif ex.free_type == ex.LAST_ENTRY:
                    # Last directory entry, do not parse any further
                    break
            else:
                dir_hdr["DIR_Name"] = dir_sn

            # Long File Names
            if FATLongDirectoryEntry.is_lfn_entry(dir_hdr["DIR_Name"],
                                                  dir_hdr["DIR_Attr"]):
                self.parse_lfn_entry(tmp_lfn_entry, hdr_addr)
                continue

            # Normal directory entries
            if not tmp_lfn_entry.is_lfn_entry_complete():
                # Ignore incomplete LFN entries altogether
                tmp_lfn_entry = None

            dir_entry = FATDirectoryEntry(encoding=self.encoding,
                                          lfn_entry=tmp_lfn_entry,
                                          **dir_hdr)
            dir_entries += [dir_entry]

            if dir_entry.is_directory() and not dir_entry.is_special():
                # Iterate all subdirectories except for dot and dotdot
                subdirs = self.parse_dir_entries_in_cluster_chain(
                    dir_entry.get_cluster())
                for d in subdirs:
                    dir_entry.add_subdirectory(d)

            # Reset temporary LFN entry
            tmp_lfn_entry = FATLongDirectoryEntry()

        return dir_entries, tmp_lfn_entry
Esempio n. 2
0
def test_bytename_set_not_a_directory_free_entry():
    """Test that 0x00 is detect as the last entry of the directory cluster."""
    sfn = EightDotThree()
    with pytest.raises(NotADirectoryError) as ex:
        sfn.set_byte_name(b'\xE5          ')
        assert ex.free_type == ex.FREE_ENTRY
Esempio n. 3
0
    def makedir(self,
                path: str,
                permissions: Permissions = None,
                recreate: bool = False):
        """Create directory on filesystem.

        :param path: Path of new directory on filesystem
        :param permissions: Currently not implemented
        :param recreate: Ignore if directory already exists
        """
        base = "/".join(path.split("/")[:-1])
        dirname = path.split("/")[-1]

        # Plausability checks
        try:
            base = self.opendir(base)
        except DirectoryExpected:
            raise ResourceNotFound(path)

        try:
            self._get_dir_entry(path)
        except ResourceNotFound:
            pass
        else:
            # TODO: Implement recreate param
            raise DirectoryExists(path)

        parent_is_root = base == self.fs.root_dir

        # Determine 8DOT3 file name + LFN
        short_name = EightDotThree()
        n = short_name.make_8dot3_name(dirname, base)
        short_name.set_str_name(n)

        newdir = FATDirectoryEntry(DIR_Name=short_name,
                                   DIR_Attr=FATDirectoryEntry.ATTR_DIRECTORY,
                                   DIR_NTRes=0,
                                   DIR_CrtTimeTenth=0,
                                   DIR_CrtDateTenth=0,
                                   DIR_LstAccessDate=0,
                                   DIR_FstClusHI=0x00,
                                   DIR_WrtTime=0,
                                   DIR_WrtDate=0,
                                   DIR_FstClusLO=0x00,
                                   DIR_FileSize=0,
                                   encoding=self.fs.encoding)

        # Create LFN entry if required
        if short_name.get_unpadded_filename() != dirname:
            lfn_entry = make_lfn_entry(dirname, short_name)
            newdir.set_lfn_entry(lfn_entry)

        # Create . and .. directory entries
        first_cluster = self.fs.allocate_bytes(
            FATDirectoryEntry.FAT_DIRECTORY_HEADER_SIZE * 2, erase=True)[0]
        newdir.set_cluster(first_cluster)
        dot_sn = EightDotThree()
        dot_sn.set_byte_name(b".          ")
        dot = FATDirectoryEntry(DIR_Name=dot_sn,
                                DIR_Attr=FATDirectoryEntry.ATTR_DIRECTORY,
                                DIR_NTRes=newdir.ntres,
                                DIR_CrtTimeTenth=newdir.crttimetenth,
                                DIR_CrtDateTenth=newdir.crtdatetenth,
                                DIR_LstAccessDate=newdir.lstaccessdate,
                                DIR_FstClusHI=newdir.fstclushi,
                                DIR_WrtTime=newdir.wrttime,
                                DIR_WrtDate=newdir.wrtdate,
                                DIR_FstClusLO=newdir.fstcluslo,
                                DIR_FileSize=newdir.filesize,
                                encoding=self.fs.encoding)
        dotdot_sn = EightDotThree()
        dotdot_sn.set_byte_name(b"..         ")
        base_fstclushi = base.fstclushi if not parent_is_root else 0x0
        base_fstcluslo = base.fstcluslo if not parent_is_root else 0x0
        dotdot = FATDirectoryEntry(DIR_Name=dotdot_sn,
                                   DIR_Attr=FATDirectoryEntry.ATTR_DIRECTORY,
                                   DIR_NTRes=base.ntres,
                                   DIR_CrtTimeTenth=base.crttimetenth,
                                   DIR_CrtDateTenth=base.crtdatetenth,
                                   DIR_LstAccessDate=base.lstaccessdate,
                                   DIR_FstClusHI=base_fstclushi,
                                   DIR_WrtTime=base.wrttime,
                                   DIR_WrtDate=base.wrtdate,
                                   DIR_FstClusLO=base_fstcluslo,
                                   DIR_FileSize=base.filesize,
                                   encoding=self.fs.encoding)
        newdir.add_subdirectory(dot)
        newdir.add_subdirectory(dotdot)

        # Write new directory contents
        self.fs.update_directory_entry(newdir)

        # Write parent directory
        base.add_subdirectory(newdir)
        self.fs.update_directory_entry(base)

        # Flush FAT(s) to disk
        self.fs.flush_fat()
Esempio n. 4
0
def test_bytename_set_invalid_length():
    """Test that a byte name can only be set with the correct length."""
    sfn = EightDotThree()
    for n in [b'', b'1234567890', b'123456789011']:
        with pytest.raises(ValueError):
            sfn.set_byte_name(n)