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; }
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; }
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; }
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; }
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; }