Esempio n. 1
0
int
add_partition_to_map(const char *name, const char *dptype, u32 base, u32 length,
	partition_map_header *map)
{
    partition_map * cur;
    DPME *data;
    enum add_action act;
    int limit;
    u32 adjusted_base = 0;
    u32 adjusted_length = 0;
    u32 new_base = 0;
    u32 new_length = 0;

	// find a block that starts includes base and length
    cur = map->base_order;
    while (cur != NULL) {
	if (cur->data->dpme_pblock_start <= base 
		&& (base + length) <=
		    (cur->data->dpme_pblock_start + cur->data->dpme_pblocks)) {
	    break;
	} else {
	    cur = cur->next_by_base;
	}
    }
	// if it is not Extra then punt
    if (cur == NULL
	    || strncmp(cur->data->dpme_type, kFreeType, DPISTRLEN) != 0) {
	printf("requested base and length is not "
		"within an existing free partition\n");
	return 0;
    }
	// figure out what to do and sizes
    data = cur->data;
    if (data->dpme_pblock_start == base) {
	// replace or add
	if (data->dpme_pblocks == length) {
	    act = kReplace;
	} else {
	    act = kAdd;
	    adjusted_base = base + length;
	    adjusted_length = data->dpme_pblocks - length;
	}
    } else {
	// split or add
	if (data->dpme_pblock_start + data->dpme_pblocks == base + length) {
	    act = kAdd;
	    adjusted_base = data->dpme_pblock_start;
	    adjusted_length = base - adjusted_base;
	} else {
	    act = kSplit;
	    new_base = data->dpme_pblock_start;
	    new_length = base - new_base;
	    adjusted_base = base + length;
	    adjusted_length = data->dpme_pblocks - (length + new_length);
	}
    }
	// if the map will overflow then punt
    if (map->maximum_in_map < 0) {
	limit = map->media_size;
    } else {
	limit = map->maximum_in_map;
    }
    if (map->blocks_in_map + act > limit) {
	printf("the map is not big enough\n");
	return 0;
    }

    data = create_data(name, dptype, base, length);
    if (data == NULL) {
	return 0;
    }
    if (act == kReplace) {
	free(cur->data);
	cur->data = data;
    } else {
	    // adjust this block's size
	cur->data->dpme_pblock_start = adjusted_base;
	cur->data->dpme_pblocks = adjusted_length;
	cur->data->dpme_lblocks = adjusted_length;
	    // insert new with block address equal to this one
	if (add_data_to_map(data, cur->disk_address, map) == 0) {
	    free(data);
	} else if (act == kSplit) {
	    data = create_data(kFreeName, kFreeType, new_base, new_length);
	    if (data != NULL) {
		    // insert new with block address equal to this one
		if (add_data_to_map(data, cur->disk_address, map) == 0) {
		    free(data);
		}
	    }
	}
    }
	// renumber disk addresses
    renumber_disk_addresses(map);
	// mark changed
    map->changed = 1;
    return 1;
}
Esempio n. 2
0
partition_map_header *
create_partition_map(char *name, partition_map_header *oldmap)
{
    media *fd;
    partition_map_header * map;
    DPME *data;
    unsigned long number;
    int size;
#ifdef __linux__
    struct stat info;
#endif

    fd = open_media(name, (rflag)?O_RDONLY:O_RDWR);
    if (fd == 0) {
	error(errno, "can't open file '%s' for %sing", name,
		(rflag)?"read":"writ");
	return NULL;
    }

    map = (partition_map_header *) malloc(sizeof(partition_map_header));
    if (map == NULL) {
	error(errno, "can't allocate memory for open partition map");
	close_media(fd);
	return NULL;
    }
    map->fd = fd;
    map->name = name;
    map->writeable = (rflag)?0:1;
    map->changed = 1;
    map->disk_order = NULL;
    map->base_order = NULL;

    if (oldmap != NULL) {
	size = oldmap->physical_block;
    } else {
	size = fd->block_size;
	if (interactive) {
	    printf("A physical block is %d bytes: ", size);
	    flush_to_newline(0);
	    get_number_argument("what should be the physical block size? ",
		    (long *)&size, size);
	    size = (size / PBLOCK_SIZE) * PBLOCK_SIZE;
	}
    }
    map->physical_block = size;
    // printf("block size is %d\n", map->physical_block);

    if (oldmap != NULL) {
	size = oldmap->logical_block;
    } else {
	size = PBLOCK_SIZE;
	if (interactive) {
	    printf("A logical block is %d bytes: ", size);
	    flush_to_newline(0);
	    get_number_argument("what should be the logical block size? ",
		    (long *)&size, size);
	    size = (size / PBLOCK_SIZE) * PBLOCK_SIZE;
	}
    }
    map->logical_block = size;
    if (map->logical_block > MAXIOSIZE) {
	map->logical_block = MAXIOSIZE;
    }
    if (map->logical_block > map->physical_block) {
	map->physical_block = map->logical_block;
    }
    map->blocks_in_map = 0;
    map->maximum_in_map = -1;

    number = compute_device_size(map, oldmap);
    if (interactive) {
	printf("size of 'device' is %lu blocks (%d byte blocks): ",
		number, map->logical_block);
	flush_to_newline(0);
	get_number_argument("what should be the size? ", 
			    (long *)&number, number);
	if (number < 4) {
	    number = 4;
	}
	printf("new size of 'device' is %lu blocks (%d byte blocks)\n",
		number, map->logical_block);
    }
    map->media_size = number;

#ifdef __linux__
    if (fstat(fd, &info) < 0) {
	error(errno, "can't stat file '%s'", name);
	map->regular_file = 0;
    } else {
	map->regular_file = S_ISREG(info.st_mode);
    }
#else
    map->regular_file = 0;
#endif

    map->misc = (Block0 *) malloc(PBLOCK_SIZE);
    if (map->misc == NULL) {
	error(errno, "can't allocate memory for block zero buffer");
    } else {
	// got it!
	coerce_block0(map);
	sync_device_size(map);
	
	data = (DPME *) calloc(1, PBLOCK_SIZE);
	if (data == NULL) {
	    error(errno, "can't allocate memory for disk buffers");
	} else {
	    // set data into entry
	    data->dpme_signature = DPME_SIGNATURE;
	    data->dpme_map_entries = 1;
	    data->dpme_pblock_start = 1;
	    data->dpme_pblocks = map->media_size - 1;
	    strncpy(data->dpme_name, kFreeName, DPISTRLEN);
	    strncpy(data->dpme_type, kFreeType, DPISTRLEN);
	    data->dpme_lblock_start = 0;
	    data->dpme_lblocks = data->dpme_pblocks;
	    dpme_writable_set(data, 1);
	    dpme_readable_set(data, 1);
	    dpme_bootable_set(data, 0);
	    dpme_in_use_set(data, 0);
	    dpme_allocated_set(data, 0);
	    dpme_valid_set(data, 1);

	    if (add_data_to_map(data, 1, map) == 0) {
		free(data);
	    } else {
		return map;
	    }
	}
    }
    close_partition_map(map);
    return NULL;
}
Esempio n. 3
0
partition_map_header *
create_partition_map(char *name, partition_map_header *oldmap, int oflag)
{
    MEDIA m;
    partition_map_header * map;
    DPME *data;
    unsigned long default_number;
    unsigned long number;
    long size;
    unsigned long multiple;

    m = open_pathname_as_media(name, oflag);
    if (m == 0) {
	error(errno, "can't open file '%s' for %sing", name,
		(oflag == O_RDONLY)?"read":"writ");
	return NULL;
    }

    map = (partition_map_header *) malloc(sizeof(partition_map_header));
    if (map == NULL) {
	error(errno, "can't allocate memory for open partition map");
	close_media(m);
	return NULL;
    }
    map->name = name;
    map->writable = (oflag == O_RDONLY)?0:1;
    map->changed = 1;
    map->disk_order = NULL;
    map->base_order = NULL;

    if (oldmap != NULL) {
	size = oldmap->physical_block;
    } else {
	size = media_granularity(m);
    }
    m = open_deblock_media(PBLOCK_SIZE, m);
    map->m = m;
    if (interactive) {
	printf("A physical block is %ld bytes: ", size);
	flush_to_newline(0);
	get_number_argument("what should be the physical block size? ",
		&size, size);
	size = (size / PBLOCK_SIZE) * PBLOCK_SIZE;
	if (size < PBLOCK_SIZE) {
	    size = PBLOCK_SIZE;
	}
    }
    if (map->physical_block > MAXIOSIZE) {
	map->physical_block = MAXIOSIZE;
    }
    map->physical_block = size;
    // printf("block size is %d\n", map->physical_block);

    if (oldmap != NULL) {
	size = oldmap->logical_block;
    } else {
	size = PBLOCK_SIZE;
    }
    if (interactive) {
	printf("A logical block is %ld bytes: ", size);
	flush_to_newline(0);
	get_number_argument("what should be the logical block size? ",
		&size, size);
	size = (size / PBLOCK_SIZE) * PBLOCK_SIZE;
	if (size < PBLOCK_SIZE) {
	    size = PBLOCK_SIZE;
	}
    }
#if 0
    if (size > map->physical_block) {
	size = map->physical_block;
    }
#endif
    map->logical_block = size;

    map->blocks_in_map = 0;
    map->maximum_in_map = -1;

    number = compute_device_size(map, oldmap);
    if (interactive) {
	printf("size of 'device' is %lu blocks (%d byte blocks): ",
		number, map->logical_block);
	default_number = number;
	flush_to_newline(0);
	do {
	    if (get_number_argument("what should be the size? ", 
		    (long *)&number, default_number) == 0) {
		printf("Not a number\n");
		flush_to_newline(1);
		number = 0;
	    } else {
		multiple = get_multiplier(map->logical_block);
		if (multiple == 0) {
		    printf("Bad multiplier\n");
		    number = 0;
		} else if (multiple != 1) {
		    if (0xFFFFFFFF/multiple < number) {
			printf("Number too large\n");
			number = 0;
		    } else {
			number *= multiple;
		    }
		}
	    }
	    default_number = kDefault;
	} while (number == 0);

	if (number < 4) {
	    number = 4;
	}
	printf("new size of 'device' is %lu blocks (%d byte blocks)\n",
		number, map->logical_block);
    }
    map->media_size = number;

    map->misc = (Block0 *) calloc(1, PBLOCK_SIZE);
    if (map->misc == NULL) {
	error(errno, "can't allocate memory for block zero buffer");
    } else {
	// got it!
	coerce_block0(map);
	sync_device_size(map);
	
	data = (DPME *) calloc(1, PBLOCK_SIZE);
	if (data == NULL) {
	    error(errno, "can't allocate memory for disk buffers");
	} else {
	    // set data into entry
	    data->dpme_signature = DPME_SIGNATURE;
	    data->dpme_map_entries = 1;
	    data->dpme_pblock_start = 1;
	    data->dpme_pblocks = map->media_size - 1;
	    strncpy(data->dpme_name, kFreeName, DPISTRLEN);
	    strncpy(data->dpme_type, kFreeType, DPISTRLEN);
	    data->dpme_lblock_start = 0;
	    data->dpme_lblocks = data->dpme_pblocks;
	    dpme_writable_set(data, 1);
	    dpme_readable_set(data, 1);
	    dpme_bootable_set(data, 0);
	    dpme_in_use_set(data, 0);
	    dpme_allocated_set(data, 0);
	    dpme_valid_set(data, 1);

	    if (add_data_to_map(data, 1, map) == 0) {
		free(data);
	    } else {
		return map;
	    }
	}
    }
    close_partition_map(map);
    return NULL;
}
Esempio n. 4
0
int
read_partition_map(partition_map_header *map)
{
    DPME *data;
    u32 limit;
    int index;
    int old_logical;
    double d;

    data = (DPME *) malloc(PBLOCK_SIZE);
    if (data == NULL) {
	error(errno, "can't allocate memory for disk buffers");
	return -1;
    }

    if (read_block(map, 1, (char *)data, 0) == 0) {
	free(data);
	return -1;
    } else if (convert_dpme(data, 1)
	    || data->dpme_signature != DPME_SIGNATURE) {
	old_logical = map->logical_block;
	map->logical_block = 512;
	while (map->logical_block <= map->physical_block) {
	    if (read_block(map, 1, (char *)data, 0) == 0) {
		free(data);
		return -1;
	    } else if (convert_dpme(data, 1) == 0
		    && data->dpme_signature == DPME_SIGNATURE) {
		d = map->media_size;
		map->media_size =  (d * old_logical) / map->logical_block;
		break;
	    }
	    map->logical_block *= 2;
	}
	if (map->logical_block > map->physical_block) {
	    free(data);
	    return -1;
	}
    }

    limit = data->dpme_map_entries;
    index = 1;
    while (1) {
	if (add_data_to_map(data, index, map) == 0) {
	    free(data);
	    return -1;
	}

	if (index >= limit) {
	    break;
	} else {
	    index++;
	}

	data = (DPME *) malloc(PBLOCK_SIZE);
	if (data == NULL) {
	    error(errno, "can't allocate memory for disk buffers");
	    return -1;
	}

	if (read_block(map, index, (char *)data, 0) == 0) {
	    free(data);
	    return -1;
	} else if (convert_dpme(data, 1)
		|| data->dpme_signature != DPME_SIGNATURE
		|| data->dpme_map_entries != limit) {
	    free(data);
	    return -1;
	}
    }
    return 0;
}
Esempio n. 5
0
int
read_partition_map(partition_map_header *map)
{
    DPME *data;
    u32 limit;
    unsigned int ix;
    int old_logical;
    double d;

//printf("called read_partition_map\n");
//printf("logical = %d, physical = %d\n", map->logical_block, map->physical_block);
    data = (DPME *) malloc(PBLOCK_SIZE);
    if (data == NULL) {
	error(errno, "can't allocate memory for disk buffers");
	return -1;
    }

    if (read_block(map, 1, (char *)data) == 0) {
	error(-1, "Can't read block 1 from '%s'", map->name);
	free(data);
	return -1;
    } else if (convert_dpme(data, 1)
	    || data->dpme_signature != DPME_SIGNATURE) {
	old_logical = map->logical_block;
	map->logical_block = 512;
	while (map->logical_block <= map->physical_block) {
	    if (read_block(map, 1, (char *)data) == 0) {
		error(-1, "Can't read block 1 from '%s'", map->name);
		free(data);
		return -1;
	    } else if (convert_dpme(data, 1) == 0
		    && data->dpme_signature == DPME_SIGNATURE) {
		d = map->media_size;
		map->media_size =  (d * old_logical) / map->logical_block;
		break;
	    }
	    map->logical_block *= 2;
	}
	if (map->logical_block > map->physical_block) {
	    error(-1, "No valid block 1 on '%s'", map->name);
	    free(data);
	    return -1;
	}
    }
//printf("logical = %d, physical = %d\n", map->logical_block, map->physical_block);

    limit = data->dpme_map_entries;
    ix = 1;
    while (1) {
	if (add_data_to_map(data, ix, map) == 0) {
	    free(data);
	    return -1;
	}

	if (ix >= limit) {
	    break;
	} else {
	    ix++;
	}

	data = (DPME *) malloc(PBLOCK_SIZE);
	if (data == NULL) {
	    error(errno, "can't allocate memory for disk buffers");
	    return -1;
	}

	if (read_block(map, ix, (char *)data) == 0) {
	    error(-1, "Can't read block %u from '%s'", ix, map->name);
	    free(data);
	    return -1;
	} else if (convert_dpme(data, 1)
		|| (data->dpme_signature != DPME_SIGNATURE && dflag == 0)
		|| (data->dpme_map_entries != limit && dflag == 0)) {
	    error(-1, "Bad data in block %u from '%s'", ix, map->name);
	    free(data);
	    return -1;
	}
    }
    return 0;
}