예제 #1
0
파일: dir.c 프로젝트: MaddTheSane/haiku
/*!	shrink directory to the size needed
	errors here are neither likely nor problematic
	w95 doesn't seem to do this, so it's possible to create a
	really large directory that consumes all available space!
*/
status_t
compact_directory(nspace *vol, vnode *dir)
{
	uint32 last = 0;
	struct diri diri;
	status_t error = B_ERROR; /* quiet warning */

	DPRINTF(0, ("compacting directory with vnode id %Lx\n", dir->vnid));

	// root directory can't shrink in fat12 and fat16
	if (IS_FIXED_ROOT(dir->cluster))
		return 0;

	if (diri_init(vol, dir->cluster, 0, &diri) == NULL) {
		dprintf("compact_directory: cannot open dir at cluster (%lx)\n",
			dir->cluster);
		return EIO;
	}
	while (diri.current_block) {
		char filename[512];
		struct _dirent_info_ info;

		error = _next_dirent_(&diri, &info, filename, 512);

		if (error == B_OK) {
			// don't compact away volume labels in the root dir
			if (!(info.mode & FAT_VOLUME) || (dir->vnid != vol->root_vnode.vnid))
				last = diri.current_index;
		} else if (error == ENOENT) {
			uint32 clusters = (last + vol->bytes_per_sector / 0x20
				* vol->sectors_per_cluster - 1) / (vol->bytes_per_sector / 0x20)
				/ vol->sectors_per_cluster;
			error = 0;

			// special case for fat32 root directory; we don't want
			// it to disappear
			if (clusters == 0)
				clusters = 1;

			if (clusters * vol->bytes_per_sector * vol->sectors_per_cluster < dir->st_size) {
				DPRINTF(0, ("shrinking directory to %lx clusters\n", clusters));
				error = set_fat_chain_length(vol, dir, clusters);
				dir->st_size = clusters*vol->bytes_per_sector*vol->sectors_per_cluster;
				dir->iteration++;
			}
			break;
		} else {
			dprintf("compact_directory: unknown error from _next_dirent_ (%s)\n",
				strerror(error));
			break;
		}
	}
	diri_free(&diri);

	return error;
}
예제 #2
0
파일: iter.c 프로젝트: yunxiaoxiao110/haiku
static off_t _csi_to_block_(struct csi *csi)
{
    // presumes the caller has already called _validate_cs_ on the argument
    ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0);
    if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
        return EINVAL;

    if (IS_FIXED_ROOT(csi->cluster))
        return csi->vol->root_start + csi->sector;

    return csi->vol->data_start +
           (off_t)(csi->cluster - 2)* csi->vol->sectors_per_cluster +
           csi->sector;
}
예제 #3
0
파일: iter.c 프로젝트: yunxiaoxiao110/haiku
static int _validate_cs_(nspace *vol, uint32 cluster, uint32 sector)
{
    if (sector < 0) return -1;

    if ((vol->fat_bits != 32) && IS_FIXED_ROOT(cluster)) { // fat12 or fat16 root
        if (sector >= vol->root_sectors)
            return -1;
        return 0;
    }

    if (sector >= vol->sectors_per_cluster) return -1;

    if (!IS_DATA_CLUSTER(cluster)) return -1;

    return 0;
}
예제 #4
0
파일: iter.c 프로젝트: yunxiaoxiao110/haiku
int iter_csi(struct csi *csi, int sectors)
{
    if (csi->sector == 0xffff) // check if already at end of chain
        return -1;

    if (sectors < 0)
        return EINVAL;

    if (sectors == 0)
        return 0;

    if (IS_FIXED_ROOT(csi->cluster)) {
        csi->sector += sectors;
        if (csi->sector < csi->vol->root_sectors)
            return 0;
    } else {
        csi->sector += sectors;
        if (csi->sector < csi->vol->sectors_per_cluster)
            return 0;
        csi->cluster = get_nth_fat_entry(csi->vol, csi->cluster, csi->sector / csi->vol->sectors_per_cluster);

        if ((int32)csi->cluster < 0) {
            csi->sector = 0xffff;
            return csi->cluster;
        }

        if (vIS_DATA_CLUSTER(csi->vol,csi->cluster)) {
            csi->sector %= csi->vol->sectors_per_cluster;
            return 0;
        }
    }

    csi->sector = 0xffff;

    return -1;
}