Beispiel #1
0
uint32_t reallocate_cluster_chain(uint32_t first_cluster, uint32_t new_size) {
    uint32_t next_cluster = first_cluster;
    uint32_t current_size = BYTES_PER_CLUSTER;

    uint8_t extending = 0;

    while (current_size < new_size) {
        if (FAT_ENTRIES[next_cluster] == FAT_EOFC_ENTRY) {
            // new size is larger than previous so extend the cluster
            extending = 1;
        }
        if (extending == 1) {
            FAT_ENTRIES[next_cluster] = find_free_cluster();
            DIR_ENTRIES[next_cluster] = DIR_ENTRIES[first_cluster];
        }

        next_cluster = FAT_ENTRIES[next_cluster];
        current_size += BYTES_PER_CLUSTER;
    }
    if (extending == 0 && FAT_ENTRIES[next_cluster] != FAT_EOFC_ENTRY) {
        // free clusters since we have shrunk current chain
        free_cluster_chain(FAT_ENTRIES[next_cluster]);
    }

    FAT_ENTRIES[next_cluster] = FAT_EOFC_ENTRY;
    DIR_ENTRIES[next_cluster] = DIR_ENTRIES[first_cluster];
    return first_cluster;
}
Beispiel #2
0
int syscall_unlink(const char *pathname)
{
	int drive;
	int curdir_handle;
	char name_comp[13], conv_name[11], dir_path[501];
	struct dir_entry dent;
	int err;

	if (strlen(pathname) > 500) return ELONGPATH;

	parse_path(pathname, &drive, dir_path, name_comp);

	if (dir_path[0] != 0)
	{
		curdir_handle = open_path(drive, dir_path);

		if (curdir_handle < 0)
			return curdir_handle;	// Error
	}
	else
	{
		curdir_handle = get_curdir_handle(drive);
		increment_ref_count(curdir_handle);
	}

	// Last file name component.
	if (convert_name(name_comp, conv_name) < 0)
	{
		err =  EINVALIDNAME; // Error
	}
	else if (find_entry(curdir_handle, conv_name, &dent) == 1)
	{	// Check whether it is a deletable file
		if ((dent.attrib & (FTYPE_READONLY | FTYPE_DIR | FTYPE_VOLUME)) == 0)
		{
			delete_dir_entry(curdir_handle, conv_name);
			free_cluster_chain(dent.start_cluster);
			err = 0;
		}
		else
		{
			err = EACCESS; // Error
		}
	}
	else 
	{
		err = EFILE_NOT_FOUND;
	}

	close_dir(curdir_handle);
	return err;
}
Beispiel #3
0
void filesystem::free_cluster_chain(uint32_t cluster)
{
	if(cluster == 2)
		throw std::runtime_error("Cluster 2 can't be freed");
	if(cluster / CLUSTERS_PER_SUPER >= supercluster_count)
		throw std::runtime_error("Bad cluster to free");
	uint32_t oldnext = superclusters[cluster / CLUSTERS_PER_SUPER].clusters[cluster % CLUSTERS_PER_SUPER];
	if(oldnext == 0)
		throw std::runtime_error("Attempted to free free cluster");
	if(oldnext == 0xFFFFFFFFU)
		throw std::runtime_error("Attempted to free system cluster");
	superclusters[cluster / CLUSTERS_PER_SUPER].clusters[cluster % CLUSTERS_PER_SUPER] = 0;
	//If there is no next block, or the next block is in different supercluster, save the cluster table.
	if(oldnext == 1 || oldnext / CLUSTERS_PER_SUPER != cluster / CLUSTERS_PER_SUPER)
		superclusters[cluster / CLUSTERS_PER_SUPER].save(backing, cluster / CLUSTERS_PER_SUPER);
	if(oldnext != 1)
		free_cluster_chain(oldnext);
}